The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
Changes 769
MANIFEST 111
META.yml 11
MYMETA.yml 11
Makefile.PL 11
README.pod 1311
lib/Mojo/Asset/File.pm 139
lib/Mojo/Asset/Memory.pm 85
lib/Mojo/Base.pm 124
lib/Mojo/ByteStream.pm 2929
lib/Mojo/Cache.pm 32
lib/Mojo/Command.pm 4122
lib/Mojo/Content/MultiPart.pm 2013
lib/Mojo/Content/Single.pm 136
lib/Mojo/Content.pm 4531
lib/Mojo/Cookie/Request.pm 105
lib/Mojo/Cookie/Response.pm 45
lib/Mojo/Cookie.pm 22
lib/Mojo/CookieJar.pm 4119
lib/Mojo/DOM.pm 11457
lib/Mojo/Date.pm 105
lib/Mojo/Exception.pm 76
lib/Mojo/Headers.pm 1411
lib/Mojo/HelloWorld.pm 612
lib/Mojo/Home.pm 78
lib/Mojo/IOLoop.pm 9776
lib/Mojo/JSON.pm 1414
lib/Mojo/Loader.pm 10118
lib/Mojo/Log.pm 88
lib/Mojo/Message/Request.pm 3737
lib/Mojo/Message/Response.pm 1216
lib/Mojo/Message.pm 7150
lib/Mojo/Parameters.pm 5147
lib/Mojo/Path.pm 811
lib/Mojo/Server/CGI.pm 32
lib/Mojo/Server/Daemon.pm 1410
lib/Mojo/Server/FastCGI.pm 2319
lib/Mojo/Server/Hypnotoad.pm 8831
lib/Mojo/Server/Morbo.pm 0193
lib/Mojo/Server/PSGI.pm 76
lib/Mojo/Server.pm 2423
lib/Mojo/Template.pm 2415
lib/Mojo/Transaction/HTTP.pm 3826
lib/Mojo/Transaction/WebSocket.pm 2716
lib/Mojo/Transaction.pm 118
lib/Mojo/URL.pm 2922
lib/Mojo/Upload.pm 75
lib/Mojo/UserAgent.pm 6152
lib/Mojo/Util.pm 3726
lib/Mojo.pm 66
lib/Mojolicious/Command/Cgi.pm 11
lib/Mojolicious/Command/Daemon.pm 41
lib/Mojolicious/Command/Eval.pm 11
lib/Mojolicious/Command/Fastcgi.pm 11
lib/Mojolicious/Command/Generate/App.pm 21
lib/Mojolicious/Command/Generate/Makefile.pm 10
lib/Mojolicious/Command/Get.pm 33
lib/Mojolicious/Command/Inflate.pm 11
lib/Mojolicious/Command/Psgi.pm 11
lib/Mojolicious/Command/Routes.pm 43
lib/Mojolicious/Command/Test.pm 11
lib/Mojolicious/Command/Version.pm 11
lib/Mojolicious/Commands.pm 2931
lib/Mojolicious/Controller.pm 5570
lib/Mojolicious/Guides/Cheatsheet.pod 70
lib/Mojolicious/Guides/Cookbook.pod 2133
lib/Mojolicious/Guides/FAQ.pod 93
lib/Mojolicious/Guides/Growing.pod 93
lib/Mojolicious/Guides/Rendering.pod 10
lib/Mojolicious/Guides/Routing.pod 411
lib/Mojolicious/Guides.pod 47
lib/Mojolicious/Lite.pm 921
lib/Mojolicious/Plugin/AgentCondition.pm 660
lib/Mojolicious/Plugin/CallbackCondition.pm 066
lib/Mojolicious/Plugin/Charset.pm 41
lib/Mojolicious/Plugin/Config.pm 55
lib/Mojolicious/Plugin/DefaultHelpers.pm 54
lib/Mojolicious/Plugin/EpRenderer.pm 48
lib/Mojolicious/Plugin/EplRenderer.pm 54
lib/Mojolicious/Plugin/HeaderCondition.pm 3642
lib/Mojolicious/Plugin/I18n.pm 94
lib/Mojolicious/Plugin/JsonConfig.pm 22
lib/Mojolicious/Plugin/Mount.pm 080
lib/Mojolicious/Plugin/PodRenderer.pm 44
lib/Mojolicious/Plugin/RequestTimer.pm 108
lib/Mojolicious/Plugin/TagHelpers.pm 1522
lib/Mojolicious/Plugins.pm 129
lib/Mojolicious/Renderer.pm 1616
lib/Mojolicious/Routes/Match.pm 1610
lib/Mojolicious/Routes/Pattern.pm 2217
lib/Mojolicious/Routes.pm 5856
lib/Mojolicious/Sessions.pm 51
lib/Mojolicious/Static.pm 2324
lib/Mojolicious/Types.pm 11
lib/Mojolicious/public/css/prettify.css 11
lib/Mojolicious/public/js/lang-apollo.js 22
lib/Mojolicious/public/js/lang-clj.js 018
lib/Mojolicious/public/js/lang-css.js 22
lib/Mojolicious/public/js/lang-go.js 01
lib/Mojolicious/public/js/lang-hs.js 22
lib/Mojolicious/public/js/lang-lisp.js 23
lib/Mojolicious/public/js/lang-lua.js 22
lib/Mojolicious/public/js/lang-ml.js 22
lib/Mojolicious/public/js/lang-n.js 04
lib/Mojolicious/public/js/lang-proto.js 11
lib/Mojolicious/public/js/lang-scala.js 22
lib/Mojolicious/public/js/lang-sql.js 22
lib/Mojolicious/public/js/lang-tex.js 01
lib/Mojolicious/public/js/lang-vb.js 22
lib/Mojolicious/public/js/lang-vhdl.js 33
lib/Mojolicious/public/js/lang-wiki.js 22
lib/Mojolicious/public/js/lang-xq.js 03
lib/Mojolicious/public/js/lang-yaml.js 22
lib/Mojolicious/public/js/prettify.js 3328
lib/Mojolicious/templates/exception.development.html.ep 2424
lib/Mojolicious/templates/perldoc.html.ep 22
lib/Mojolicious.pm 5646
lib/Test/Mojo.pm 3028
lib/ojo.pm 11
script/hypnotoad 12
script/mojo 11
script/morbo 079
t/mojo/bytestream.t 718
t/mojo/command.t 147
t/mojo/cookiejar.t 1224
t/mojo/date.t 22
t/mojo/dom.t 120
t/mojo/hypnotoad.t 31
t/mojo/ioloop_online.t 11
t/mojo/loader.t 281
t/mojo/message.t 33
t/mojo/morbo.t 0167
t/mojo/parameters.t 125
t/mojo/template.t 2832
t/mojo/url.t 1112
t/mojolicious/app.t 64
t/mojolicious/dispatch.t 44
t/mojolicious/embedded_lite_app.t 4111
t/mojolicious/exception_lite_app.t 920
t/mojolicious/external/myapp.pl 235
t/mojolicious/external/templates/index.html.ep 02
t/mojolicious/external_lite_app.t 212
t/mojolicious/lib/MojoliciousTest/Exceptional.pm 11
t/mojolicious/lib/MojoliciousTest/Foo.pm 11
t/mojolicious/lite_app.t 2598
t/mojolicious/ojo.t 54
t/mojolicious/production_app.t 64
t/mojolicious/tag_helper_lite_app.t 459
t/mojolicious/testing_app.t 64
149 files changed (This is a version diff) 20562638
@@ -1,5 +1,67 @@
 This file documents the revision history for Perl extension Mojolicious.
 
+1.48    2011-06-24 00:00:00
+        - Added debug log message for missing action to router.
+        - Improved Mojo::Command tests.
+        - Improved documentation.
+        - Fixed support for multiple checkboxes with same name in
+          Mojolicious::Plugin::TagHelper. (sri, kimoto)
+        - Fixed portability issue in "lite_app.t". (marcus)
+
+1.47    2011-06-22 00:00:00
+        - Added EXPERIMENTAL callback condition plugin.
+        - Added EXPERIMENTAL host condition to
+          Mojolicious::Plugin::HeaderCondition.
+        - Added host support to Mojolicious::Plugin::Mount. (sri, alnewkirk)
+        - Removed Mojolicious::Plugin::AgentCondition and added its
+          functionality to Mojolicious::Plugin::HeaderCondition.
+        - Improved overall performance slightly.
+        - Improved documentation.
+        - Fixed render_static return value.
+        - Fixed dispatcher return values.
+
+1.46    2011-06-21 00:00:00
+        - Improved Morbo to only attempt restarting applications after a file
+          change has been detected.
+        - Improved overall performance by about 3% with many small
+          optimizations.
+        - Improved query string support in Mojo::Parameters.
+        - Improved tests.
+        - Fixed Windows restart issues in Morbo. (lammel)
+        - Fixed missing plugin error message.
+
+1.45    2011-06-20 00:00:00
+        - Improved documentation.
+        - Fixed an exception with layout rendering bug.
+        - Fixed small Mojo::Parameters bug.
+
+1.44    2011-06-18 00:00:00
+        - Added EXPERIMENTAL self-restarting Morbo development web server and
+          removed old "--reload" support since there have been too many
+          negative side effects.
+          This also improves overall performance by about 5-10% and reduces
+          memory usage by about 10%.
+        - Added EXPERIMENTAL application mount plugin.
+        - Added EXPERIMENTAL --help support for all commands.
+        - Updated prettify.js to version 1-Jun-2011.
+        - Updated WebSocket diagnostics test in Mojo::HelloWorld for latest
+          Firefox Aurora.
+        - Improved inline template and static file performance.
+        - Improved whitespace trimming in Mojo::DOM. (sri, DaTa)
+        - Improved documentation.
+        - Improved tests.
+        - Fixed Morbo file discovery bug. (crab)
+        - Fixed a few application embedding bugs.
+        - Fixed link generation bug in Mojolicious::Plugin::PodRenderer.
+        - Fixed small embedding bug in Mojolicious::Plugin::RequestTimer.
+
+1.43    2011-06-13 00:00:00
+        - Improved after_dispatch hook by allowing it to change session data.
+        - Improved documentation.
+        - Fixed a bug in Mojo::Template that caused template blocks to be
+          auto escaped.
+        - Fixed typos.
+
 1.42    2011-06-09 00:00:00
         - Added EXPERIMENTAL support for unquoted wildcard placeholders in
           Mojolicious::Routes::Pattern.
@@ -215,7 +277,7 @@ This file documents the revision history for Perl extension Mojolicious.
         - Added more Perl-ish configuration plugin.
         - Added drain callback support for WebSockets.
         - Added line numbers to Mojo::JSON error messages. (marcus)
-        - Removed experimental status from hypnotoad and
+        - Removed experimental status from Hypnotoad and
           Mojolicious::Plugin::TagHelpers.
         - Removed experimental status from many attributes and methods all
           over Mojolicious.
@@ -238,7 +300,7 @@ This file documents the revision history for Perl extension Mojolicious.
         - Fixed Mojo::Client async mode.
         - Fixed session cookie encoding bug.
         - Fixed small route bug.
-        - Fixed small hypnotoad bug. (bduggan)
+        - Fixed small Hypnotoad bug. (bduggan)
 
 1.1     2011-02-14 00:00:00
         - Code name "Smiling Cat Face With Heart-Shaped Eyes", this is a
@@ -498,7 +560,7 @@ This file documents the revision history for Perl extension Mojolicious.
           Mojolicious::Plugin::JsonConfig. (marcus)
         - Added reserved route name current.
         - Simplified transaction pausing by replacing it with an automatism.
-        - Improved RFC3986 compliance of Mojo::Path. (janus)
+        - Improved RFC 3986 compliance of Mojo::Path. (janus)
         - Improved Mojo::Server::PSGI to preload applications.
         - Improved FastCGI detection for Dreamhost. (garu)
         - Improved keep alive timeout handling in Mojo::Client.
@@ -1195,7 +1257,7 @@ This file documents the revision history for Perl extension Mojolicious.
         - Updated Mojo::Server::FastCGI and Mojo::Server::Daemon::Prefork to
           use the application logger.
         - Fixed import problem in Mojo::Server::Daemon::Prefork. (James Duncan)
-        - Fixed warning in template.t.
+        - Fixed warning in "template.t".
 
 0.991238 2009-07-16 00:00:00
         - Fixed all shebang lines.
@@ -1226,7 +1288,7 @@ This file documents the revision history for Perl extension Mojolicious.
         - Simplified Mojo::Home.
         - Moved executable detection to Test::Mojo::Server.
         - Improved Mojo::Loader::Exception.
-        - Moved persistent_error.t tests to app.t.
+        - Moved "persistent_error.t" tests to "app.t".
         - Cleaned up code.
         - Fixed at_least_version. (yuki-kimoto)
 
@@ -1394,7 +1456,7 @@ This file documents the revision history for Perl extension Mojolicious.
 0.8007  2008-11-07 00:00:00
         - Cleaned up the api some more.
         - Added param to Mojo::Message.
-        - Added server.t. (Mark Stosberg)
+        - Added "server.t". (Mark Stosberg)
         - Added documentation. (Mark Stosberg)
         - Cleaned up Mojo::File api.
         - Fixed infinite loop in Mojo::File. (Leon Brocard)
@@ -1433,7 +1495,7 @@ This file documents the revision history for Perl extension Mojolicious.
         - Removed OS X resource fork files.
 
 0.8.1   2008-11-01 00:00:00
-        - Made daemon.t developer only.
+        - Made "daemon.t" developer only.
         - Fixed typos.
 
 0.8     2008-10-21 00:00:00
@@ -38,6 +38,7 @@ lib/Mojo/Server/CGI.pm
 lib/Mojo/Server/Daemon.pm
 lib/Mojo/Server/FastCGI.pm
 lib/Mojo/Server/Hypnotoad.pm
+lib/Mojo/Server/Morbo.pm
 lib/Mojo/Server/PSGI.pm
 lib/Mojo/Template.pm
 lib/Mojo/Transaction.pm
@@ -76,7 +77,7 @@ lib/Mojolicious/Guides/Rendering.pod
 lib/Mojolicious/Guides/Routing.pod
 lib/Mojolicious/Lite.pm
 lib/Mojolicious/Plugin.pm
-lib/Mojolicious/Plugin/AgentCondition.pm
+lib/Mojolicious/Plugin/CallbackCondition.pm
 lib/Mojolicious/Plugin/Charset.pm
 lib/Mojolicious/Plugin/Config.pm
 lib/Mojolicious/Plugin/DefaultHelpers.pm
@@ -85,6 +86,7 @@ lib/Mojolicious/Plugin/EpRenderer.pm
 lib/Mojolicious/Plugin/HeaderCondition.pm
 lib/Mojolicious/Plugin/I18n.pm
 lib/Mojolicious/Plugin/JsonConfig.pm
+lib/Mojolicious/Plugin/Mount.pm
 lib/Mojolicious/Plugin/PodRenderer.pm
 lib/Mojolicious/Plugin/PoweredBy.pm
 lib/Mojolicious/Plugin/RequestTimer.pm
@@ -97,17 +99,22 @@ lib/Mojolicious/public/failraptor.png
 lib/Mojolicious/public/favicon.ico
 lib/Mojolicious/public/js/jquery.js
 lib/Mojolicious/public/js/lang-apollo.js
+lib/Mojolicious/public/js/lang-clj.js
 lib/Mojolicious/public/js/lang-css.js
+lib/Mojolicious/public/js/lang-go.js
 lib/Mojolicious/public/js/lang-hs.js
 lib/Mojolicious/public/js/lang-lisp.js
 lib/Mojolicious/public/js/lang-lua.js
 lib/Mojolicious/public/js/lang-ml.js
+lib/Mojolicious/public/js/lang-n.js
 lib/Mojolicious/public/js/lang-proto.js
 lib/Mojolicious/public/js/lang-scala.js
 lib/Mojolicious/public/js/lang-sql.js
+lib/Mojolicious/public/js/lang-tex.js
 lib/Mojolicious/public/js/lang-vb.js
 lib/Mojolicious/public/js/lang-vhdl.js
 lib/Mojolicious/public/js/lang-wiki.js
+lib/Mojolicious/public/js/lang-xq.js
 lib/Mojolicious/public/js/lang-yaml.js
 lib/Mojolicious/public/js/prettify.js
 lib/Mojolicious/public/mojolicious-arrow.png
@@ -141,6 +148,7 @@ MYMETA.yml
 README.pod
 script/hypnotoad
 script/mojo
+script/morbo
 t/mojo/apache_cgi.t
 t/mojo/apache_fastcgi.t
 t/mojo/app.t
@@ -184,6 +192,7 @@ t/mojo/lib/test.mt
 t/mojo/lib/utf8_exception.mt
 t/mojo/loader.t
 t/mojo/message.t
+t/mojo/morbo.t
 t/mojo/parameters.t
 t/mojo/path.t
 t/mojo/psgi.t
@@ -203,6 +212,7 @@ t/mojolicious/external/myapp.conf
 t/mojolicious/external/myapp.pl
 t/mojolicious/external/myapp.testing.conf
 t/mojolicious/external/public/index.html
+t/mojolicious/external/templates/index.html.ep
 t/mojolicious/external_lite_app.t
 t/mojolicious/i18n_lite_app.t
 t/mojolicious/i18n_shortcut_lite_app.t
@@ -1,6 +1,6 @@
 --- #YAML:1.0
 name:               Mojolicious
-version:            1.42
+version:            1.48
 abstract:           The Web In A Box!
 author:
     - Sebastian Riedel <sri@cpan.org>
@@ -57,4 +57,4 @@ resources:
   homepage: http://mojolicio.us
   license: http://dev.perl.org/licenses/
   repository: http://github.com/kraih/mojo
-version: 1.42
+version: 1.48
@@ -42,7 +42,7 @@ WriteMakefile(
     )
   ),
 
-  EXE_FILES => ['script/mojo', 'script/hypnotoad'],
+  EXE_FILES => ['script/hypnotoad', 'script/mojo', 'script/morbo'],
   PREREQ_PM => {
     'B'                     => 0,
     'Carp'                  => 0,
@@ -38,12 +38,12 @@ TLS, Bonjour, IDNA, Comet (long polling), chunking and multipart support.
 
 =item *
 
-Builtin async IO web server supporting epoll, kqueue, UNIX domain sockets and
-hot deployment, perfect for embedding.
+Built-in async IO web server supporting epoll, kqueue, UNIX domain sockets
+and hot deployment, perfect for embedding.
 
 =item *
 
-Automatic CGI, FastCGI, and L<PSGI> detection.
+Automatic CGI, FastCGI and L<PSGI> detection.
 
 =item *
 
@@ -71,8 +71,8 @@ These three lines are a whole web application.
 
   app->start;
 
-To run this example with the built-in development server just put the code
-into a file and execute it with C<perl>.
+To run this example with the built-in development web server just put the
+code into a file and execute it with C<perl>.
 
   % perl hello.pl daemon
   Server available at http://127.0.0.1:3000.
@@ -93,10 +93,9 @@ Web development for humans, making hard things possible and everything fun.
   get '/time' => 'clock';
 
   # RESTful web service sending JSON responses
-  get '/:offset' => sub {
-    my $self   = shift;
-    my $offset = $self->param('offset') || 23;
-    $self->render_json({list => [0 .. $offset]});
+  get '/list/:offset' => sub {
+    my $self = shift;
+    $self->render_json({list => [0 .. $self->param('offset')]});
   };
 
   # Scrape and return information from remote sites
@@ -141,9 +140,8 @@ A controller collects several actions together.
 
   # RESTful web service sending JSON responses
   sub restful {
-    my $self   = shift;
-    my $offset = $self->param('offset') || 23;
-    $self->render_json({list => [0 .. $offset]});
+    my $self = shift;
+    $self->render_json({list => [0 .. $self->param('offset')]});
   }
 
   # Scrape and return information from remote sites
@@ -191,7 +189,7 @@ especially when working in a team.
     # (paths are relative to the controller)
     $example->get('/')->to('#hello');
     $example->get('/time')->to('#clock');
-    $example->get('/:offset')->to('#restful');
+    $example->get('/list/:offset')->to('#restful');
 
     # All common HTTP verbs are supported
     $example->post('/title')->to('#title');
@@ -15,11 +15,9 @@ has [qw/cleanup path/];
 has handle => sub {
   my $self = shift;
 
-  # Handle
-  my $handle = IO::File->new;
-
   # Already got a file without handle
-  my $file = $self->path;
+  my $handle = IO::File->new;
+  my $file   = $self->path;
   if ($file && -f $file) {
     $handle->open("< $file")
       or croak qq/Can't open file "$file": $!/;
@@ -43,7 +41,7 @@ has handle => sub {
   # Open for read/write access
   $handle->fdopen(fileno($fh), "+>") or croak qq/Can't open file "$name": $!/;
 
-  return $handle;
+  $handle;
 };
 has tmpdir => sub { $ENV{MOJO_TMPDIR} || File::Spec->tmpdir };
 
@@ -53,8 +51,6 @@ has tmpdir => sub { $ENV{MOJO_TMPDIR} || File::Spec->tmpdir };
 #  claws!"
 sub DESTROY {
   my $self = shift;
-
-  # Cleanup
   my $path = $self->path;
   if ($self->cleanup && -f $path) {
     close $self->handle;
@@ -73,7 +69,7 @@ sub add_chunk {
   utf8::encode $chunk if utf8::is_utf8 $chunk;
   $self->handle->syswrite($chunk, length $chunk);
 
-  return $self;
+  $self;
 }
 
 sub contains {
@@ -107,7 +103,7 @@ sub contains {
     substr $window, 0, $read, '';
   }
 
-  return -1;
+  -1;
 }
 
 sub get_chunk {
@@ -131,7 +127,7 @@ sub get_chunk {
   }
   else { $self->handle->sysread($buffer, $size) }
 
-  return $buffer;
+  $buffer;
 }
 
 sub move_to {
@@ -150,7 +146,7 @@ sub move_to {
   # Don't clean up a moved file
   $self->cleanup(0);
 
-  return $self;
+  $self;
 }
 
 sub size {
@@ -160,7 +156,7 @@ sub size {
   my $file = $self->path;
   return -s $file if $file;
 
-  return 0;
+  0;
 }
 
 sub slurp {
@@ -173,7 +169,7 @@ sub slurp {
   my $content = '';
   while ($self->handle->sysread(my $buffer, 131072)) { $content .= $buffer }
 
-  return $content;
+  $content;
 }
 
 1;
@@ -10,14 +10,14 @@ use IO::File;
 sub new {
   my $self = shift->SUPER::new(@_);
   $self->{content} = '';
-  return $self;
+  $self;
 }
 
 sub add_chunk {
   my ($self, $chunk) = @_;
   utf8::encode $chunk if utf8::is_utf8 $chunk;
   $self->{content} .= $chunk if defined $chunk;
-  return $self;
+  $self;
 }
 
 sub contains {
@@ -29,7 +29,7 @@ sub contains {
   my $end = $self->end_range;
 
   return -1 if $end && $pos >= $end;
-  return $pos;
+  $pos;
 }
 
 sub get_chunk {
@@ -41,18 +41,15 @@ sub get_chunk {
     $size = $end + 1 - $start if ($start + $size) > $end;
   }
 
-  return substr shift->{content}, $start, $size;
+  substr shift->{content}, $start, $size;
 }
 
 sub move_to {
   my ($self, $path) = @_;
-
-  # Write
   my $file = IO::File->new;
   $file->open("> $path") or croak qq/Can't open file "$path": $!/;
   $file->syswrite($self->{content});
-
-  return $self;
+  $self;
 }
 
 sub size { length shift->{content} }
@@ -13,13 +13,8 @@ require Carp;
 #  The lesson is, never try."
 sub import {
   my $class = shift;
-
-  # Flag
   return unless my $flag = shift;
 
-  # Caller
-  my $caller = caller;
-
   # No limits!
   no strict 'refs';
   no warnings 'redefine';
@@ -35,6 +30,7 @@ sub import {
   }
 
   # ISA
+  my $caller = caller;
   push @{"${caller}::ISA"}, $flag;
 
   # Can haz?
@@ -50,9 +46,7 @@ sub import {
 
 sub new {
   my $class = shift;
-
-  # Instantiate
-  return bless
+  bless
     exists $_[0] ? exists $_[1] ? {@_} : {%{$_[0]}} : {},
     ref $class || $class;
 }
@@ -70,9 +64,6 @@ sub attr {
   return unless $class && $attrs;
   $class = ref $class || $class;
 
-  # Allow symbolic references
-  no strict 'refs';
-
   # Check default
   Carp::croak('Default has to be a code reference or constant value')
     if ref $default && ref $default ne 'CODE';
@@ -115,12 +106,13 @@ sub attr {
     $code .= "$ws\$_[0]->{'$attr'} = \$_[1];\n";
 
     # Return invocant
-    $code .= "${ws}return \$_[0];\n";
+    $code .= "${ws}\$_[0];\n";
 
     # Footer
     $code .= '};';
 
     # We compile custom attribute code for speed
+    no strict 'refs';
     no warnings 'redefine';
     *{"${class}::$attr"} = eval $code;
 
@@ -5,14 +5,14 @@ use overload '""' => sub { shift->to_string }, fallback => 1;
 use Mojo::Util;
 
 sub import {
-  return unless @_ > 1;
+  my $class = shift;
+  return unless @_ > 0;
 
   # Alternative constructor
   no strict 'refs';
   no warnings 'redefine';
   my $caller = caller;
-  *{"${caller}::b"} =
-    sub { bless {bytestream => join('', @_)}, 'Mojo::ByteStream' };
+  *{"${caller}::b"} = sub { bless {bytestream => join('', @_)}, $class };
 }
 
 # "Do we have any food that wasn't brutally slaughtered?
@@ -20,36 +20,36 @@ sub import {
 sub new {
   my $self = shift->SUPER::new();
   $self->{bytestream} = join '', @_;
-  return $self;
+  $self;
 }
 
 sub b64_decode {
   my $self = shift;
   $self->{bytestream} = Mojo::Util::b64_decode($self->{bytestream});
-  return $self;
+  $self;
 }
 
 sub b64_encode {
   my $self = shift;
   $self->{bytestream} = Mojo::Util::b64_encode($self->{bytestream}, @_);
-  return $self;
+  $self;
 }
 
 sub camelize {
   my $self = shift;
   Mojo::Util::camelize $self->{bytestream};
-  return $self;
+  $self;
 }
 
 sub clone {
   my $self = shift;
-  return $self->new($self->{bytestream});
+  $self->new($self->{bytestream});
 }
 
 sub decamelize {
   my $self = shift;
   Mojo::Util::decamelize $self->{bytestream};
-  return $self;
+  $self;
 }
 
 # "I want to share something with you: The three little sentences that will
@@ -60,61 +60,61 @@ sub decamelize {
 sub decode {
   my $self = shift;
   Mojo::Util::decode shift || 'UTF-8', $self->{bytestream};
-  return $self;
+  $self;
 }
 
 sub encode {
   my $self = shift;
   Mojo::Util::encode shift || 'UTF-8', $self->{bytestream};
-  return $self;
+  $self;
 }
 
 sub hmac_md5_sum {
   my $self = shift;
   $self->{bytestream} = Mojo::Util::hmac_md5_sum $self->{bytestream}, @_;
-  return $self;
+  $self;
 }
 
 sub hmac_sha1_sum {
   my $self = shift;
   $self->{bytestream} = Mojo::Util::hmac_sha1_sum $self->{bytestream}, @_;
-  return $self;
+  $self;
 }
 
 sub html_escape {
   my $self = shift;
   Mojo::Util::html_escape $self->{bytestream};
-  return $self;
+  $self;
 }
 
 sub html_unescape {
   my $self = shift;
   Mojo::Util::html_unescape $self->{bytestream};
-  return $self;
+  $self;
 }
 
 sub md5_bytes {
   my $self = shift;
   $self->{bytestream} = Mojo::Util::md5_bytes $self->{bytestream};
-  return $self;
+  $self;
 }
 
 sub md5_sum {
   my $self = shift;
   $self->{bytestream} = Mojo::Util::md5_sum $self->{bytestream};
-  return $self;
+  $self;
 }
 
 sub punycode_decode {
   my $self = shift;
   Mojo::Util::punycode_decode $self->{bytestream};
-  return $self;
+  $self;
 }
 
 sub punycode_encode {
   my $self = shift;
   Mojo::Util::punycode_encode $self->{bytestream};
-  return $self;
+  $self;
 }
 
 # "Old people don't need companionship.
@@ -123,19 +123,19 @@ sub punycode_encode {
 sub qp_decode {
   my $self = shift;
   Mojo::Util::qp_decode $self->{bytestream};
-  return $self;
+  $self;
 }
 
 sub qp_encode {
   my $self = shift;
   Mojo::Util::qp_encode $self->{bytestream};
-  return $self;
+  $self;
 }
 
 sub quote {
   my $self = shift;
   Mojo::Util::quote $self->{bytestream};
-  return $self;
+  $self;
 }
 
 sub say {
@@ -148,13 +148,13 @@ sub say {
 sub sha1_bytes {
   my $self = shift;
   $self->{bytestream} = Mojo::Util::sha1_bytes $self->{bytestream};
-  return $self;
+  $self;
 }
 
 sub sha1_sum {
   my $self = shift;
   $self->{bytestream} = Mojo::Util::sha1_sum $self->{bytestream};
-  return $self;
+  $self;
 }
 
 sub size { length shift->{bytestream} }
@@ -164,31 +164,31 @@ sub to_string { shift->{bytestream} }
 sub trim {
   my $self = shift;
   Mojo::Util::trim $self->{bytestream}, @_;
-  return $self;
+  $self;
 }
 
 sub unquote {
   my $self = shift;
   Mojo::Util::unquote $self->{bytestream}, @_;
-  return $self;
+  $self;
 }
 
 sub url_escape {
   my $self = shift;
   Mojo::Util::url_escape $self->{bytestream}, @_;
-  return $self;
+  $self;
 }
 
 sub url_unescape {
   my $self = shift;
   Mojo::Util::url_unescape $self->{bytestream};
-  return $self;
+  $self;
 }
 
 sub xml_escape {
   my $self = shift;
   Mojo::Util::xml_escape $self->{bytestream};
-  return $self;
+  $self;
 }
 
 1;
@@ -14,16 +14,15 @@ sub get { (shift->{_cache} || {})->{shift()} }
 sub set {
   my ($self, $key, $value) = @_;
 
+  # Cache with size limit
   my $keys  = $self->max_keys;
   my $cache = $self->{_cache} ||= {};
   my $stack = $self->{_stack} ||= [];
-
-  # Cache with size limit
   delete $cache->{shift @$stack} while @$stack >= $keys;
   push @$stack, $key;
   $cache->{$key} = $value;
 
-  return $self;
+  $self;
 }
 
 1;
@@ -38,7 +38,7 @@ sub chmod_file {
   chmod $mod, $path or croak qq/Can't chmod path "$path": $!/;
   $mod = sprintf '%lo', $mod;
   print "  [chmod] $path $mod\n" unless $self->quiet;
-  return $self;
+  $self;
 }
 
 sub chmod_rel_file {
@@ -50,13 +50,13 @@ sub class_to_file {
   my ($self, $class) = @_;
   $class =~ s/:://g;
   decamelize $class;
-  return $class;
+  $class;
 }
 
 sub class_to_path {
   my ($self, $class) = @_;
   my $path = join '/', split /::/, $class;
-  return "$path.pm";
+  "$path.pm";
 }
 
 sub create_dir {
@@ -71,7 +71,7 @@ sub create_dir {
   # Create
   File::Path::mkpath($path) or croak qq/Can't make directory "$path": $!/;
   print "  [mkdir] $path\n" unless $self->quiet;
-  return $self;
+  $self;
 }
 
 sub create_rel_dir {
@@ -96,31 +96,19 @@ sub detect {
   return 'fastcgi' if !defined $ENV{WINDIR} && !defined $ENV{USER};
 
   # Nothing
-  return;
+  undef;
 }
 
 sub get_all_data {
   my ($self, $class) = @_;
   $class ||= ref $self;
 
-  # Handle
+  # Refresh or use cached data
   my $d = do { no strict 'refs'; \*{"$class\::DATA"} };
-
-  # Refresh
-  if (fileno $d) {
-
-    # Reset
-    seek $d, 0, 0;
-
-    # Slurp
-    $CACHE->{$class} = join '', <$d>;
-
-    # Close
-    close $d;
-  }
-
-  # Content
-  return unless defined(my $content = $CACHE->{$class});
+  return $CACHE->{$class} unless fileno $d;
+  seek $d, 0, 0;
+  my $content = join '', <$d>;
+  close $d;
 
   # Ignore everything before __DATA__ (windows will seek to start of file)
   $content =~ s/^.*\n__DATA__\r?\n/\n/s;
@@ -130,25 +118,23 @@ sub get_all_data {
 
   # Split
   my @data = split /^@@\s+(.+?)\s*\r?\n/m, $content;
-
-  # Remove split garbage
   shift @data;
 
   # Find data
-  my $all = {};
+  my $all = $CACHE->{$class} = {};
   while (@data) {
     my ($name, $content) = splice @data, 0, 2;
     b64_decode $content if $name =~ s/\s*\(\s*base64\s*\)$//;
     $all->{$name} = $content;
   }
 
-  return $all;
+  $all;
 }
 
 sub get_data {
   my ($self, $data, $class) = @_;
   my $all = $self->get_all_data($class);
-  return $all->{$data};
+  $all->{$data};
 }
 
 # "You don’t like your job, you don’t strike.
@@ -162,19 +148,19 @@ sub help {
 sub rel_dir {
   my ($self, $path) = @_;
   my @parts = split /\//, $path;
-  return File::Spec->catdir(Cwd::getcwd(), @parts);
+  File::Spec->catdir(Cwd::getcwd(), @parts);
 }
 
 sub rel_file {
   my ($self, $path) = @_;
   my @parts = split /\//, $path;
-  return File::Spec->catfile(Cwd::getcwd(), @parts);
+  File::Spec->catfile(Cwd::getcwd(), @parts);
 }
 
 sub render_data {
   my $self = shift;
   my $data = shift;
-  return $self->renderer->render($self->get_data($data), @_);
+  $self->renderer->render($self->get_data($data), @_);
 }
 
 sub render_to_file {
@@ -182,7 +168,7 @@ sub render_to_file {
   my $data = shift;
   my $path = shift;
   $self->write_file($path, $self->render_data($data, @_));
-  return $self;
+  $self;
 }
 
 sub render_to_rel_file {
@@ -207,6 +193,7 @@ sub run {
     # Help
     my $help = $name eq 'help' ? 1 : 0;
     $name = shift @args if $help;
+    $help = 1           if $ENV{MOJO_HELP};
 
     # Try all namespaces
     my $module;
@@ -296,24 +283,18 @@ sub run {
   }
   print $self->hint;
 
-  return $self;
+  $self;
 }
 
 sub start {
   my $self = shift;
 
-  # Don't run commands if we are reloading
-  return $self if $ENV{MOJO_COMMANDS_DONE};
-  $ENV{MOJO_COMMANDS_DONE} ||= 1;
-
   # Executable
   $ENV{MOJO_EXE} ||= (caller)[1] if $ENV{MOJO_APP};
 
-  # Arguments
-  my @args = @_ ? @_ : @ARGV;
-
   # Run
-  return ref $self ? $self->run(@args) : $self->new->run(@args);
+  my @args = @_ ? @_ : @ARGV;
+  ref $self ? $self->run(@args) : $self->new->run(@args);
 }
 
 sub write_file {
@@ -333,7 +314,7 @@ sub write_file {
   $file->syswrite($data);
   print "  [write] $path\n" unless $self->quiet;
 
-  return $self;
+  $self;
 }
 
 sub write_rel_file {
@@ -16,8 +16,7 @@ sub body_contains {
     $found += $part->body_contains($chunk);
   }
 
-  # Found
-  return $found ? 1 : 0;
+  $found ? 1 : 0;
 }
 
 sub body_size {
@@ -27,11 +26,8 @@ sub body_size {
   my $content_length = $self->headers->content_length;
   return $content_length if $content_length;
 
-  # Boundary
-  my $boundary = $self->build_boundary;
-
   # Calculate length of whole body
-  my $boundary_length = length($boundary) + 6;
+  my $boundary_length = length($self->build_boundary) + 6;
   my $len             = 0;
   $len += $boundary_length - 2;
   for my $part (@{$self->parts}) {
@@ -46,7 +42,7 @@ sub body_size {
     $len += $boundary_length;
   }
 
-  return $len;
+  $len;
 }
 
 sub build_boundary {
@@ -79,7 +75,7 @@ sub build_boundary {
   my $after  = $2 || '';
   $headers->content_type("$before; boundary=$boundary$after");
 
-  return $boundary;
+  $boundary;
 }
 
 sub get_body_chunk {
@@ -88,12 +84,10 @@ sub get_body_chunk {
   # Body generator
   return $self->generate_body_chunk($offset) if $self->on_read;
 
-  # Multipart
+  # First boundary
   my $boundary        = $self->build_boundary;
   my $boundary_length = length($boundary) + 6;
   my $len             = $boundary_length - 2;
-
-  # First boundary
   return substr "--$boundary\x0d\x0a", $offset if $len > $offset;
 
   # Parts
@@ -142,16 +136,14 @@ sub parse {
   # Parse multipart content
   $self->_parse_multipart;
 
-  return $self;
+  $self;
 }
 
 sub _parse_multipart {
   my $self = shift;
 
-  # Need a boundary
-  my $boundary = $self->is_multipart;
-
   # Parse
+  my $boundary = $self->is_multipart;
   while (1) {
 
     # Done
@@ -193,7 +185,7 @@ sub _parse_multipart_body {
   my $chunk = substr $self->{_b2}, 0, $pos, '';
   $self->parts->[-1] = $self->parts->[-1]->parse($chunk);
   $self->{_multi_state} = 'multipart_boundary';
-  return 1;
+  1;
 }
 
 sub _parse_multipart_boundary {
@@ -218,7 +210,7 @@ sub _parse_multipart_boundary {
     $self->{_state} = $self->{_multi_state} = 'done';
   }
 
-  return;
+  undef;
 }
 
 sub _parse_multipart_preamble {
@@ -235,7 +227,7 @@ sub _parse_multipart_preamble {
   }
 
   # No boundary yet
-  return;
+  undef;
 }
 
 1;
@@ -267,7 +259,8 @@ and implements the following new ones.
 
   my $parts = $content->parts;
 
-Content parts embedded in this multipart content.
+Content parts embedded in this multipart content, usually
+L<Mojo::Content::Single> objects.
 
 =head1 METHODS
 
@@ -302,7 +295,7 @@ Get a chunk of content starting from a specfic position.
 
   $content = $content->parse('Content-Type: multipart/mixed');
 
-Parse content.
+Parse content chunk.
 
 =head1 SEE ALSO
 
@@ -9,18 +9,14 @@ has asset => sub { Mojo::Asset::Memory->new };
 
 sub body_contains {
   my ($self, $chunk) = @_;
-
-  # Found
   return 1 if $self->asset->contains($chunk) >= 0;
-
-  # Not found
-  return 0;
+  0;
 }
 
 sub body_size {
   my $self = shift;
   return ($self->headers->content_length || 0) if $self->on_read;
-  return $self->asset->size;
+  $self->asset->size;
 }
 
 sub get_body_chunk {
@@ -30,7 +26,7 @@ sub get_body_chunk {
   return $self->generate_body_chunk($offset) if $self->on_read;
 
   # Normal content
-  return $self->asset->get_chunk($offset);
+  $self->asset->get_chunk($offset);
 }
 
 sub parse {
@@ -42,9 +38,6 @@ sub parse {
   # Still parsing headers or using a custom body parser
   return $self if ($self->{_state} || '') eq 'headers' || $self->on_read;
 
-  # Headers
-  my $headers = $self->headers;
-
   # Content needs to be upgraded to multipart
   if ($self->is_multipart) {
     return $self if $self->isa('Mojo::Content::MultiPart');
@@ -82,7 +75,7 @@ sub parse {
     $self->{_state} = 'done' if $len <= $self->progress;
   }
 
-  return $self;
+  $self;
 }
 
 1;
@@ -114,7 +107,7 @@ implements the following new ones.
   my $asset = $content->asset;
   $content  = $content->asset(Mojo::Asset::Memory->new);
 
-The actual content.
+The actual content, defaults to a L<Mojo::Asset::Memory> object.
 
 =head1 METHODS
 
@@ -143,7 +136,7 @@ Get a chunk of content starting from a specfic position.
 
   $content = $content->parse("Content-Length: 12\r\n\r\nHello World!");
 
-Parse content.
+Parse content chunk.
 
 =head1 SEE ALSO
 
@@ -20,6 +20,7 @@ sub body_size { croak 'Method "body_size" not implemented by subclass' }
 sub build_body {
   my $self = shift;
 
+  # Concatenate all chunks in memory
   my $body   = '';
   my $offset = 0;
   while (1) {
@@ -36,12 +37,13 @@ sub build_body {
     $body .= $chunk;
   }
 
-  return $body;
+  $body;
 }
 
 sub build_headers {
   my $self = shift;
 
+  # Concatenate all chunks in memory
   my $headers = '';
   my $offset  = 0;
   while (1) {
@@ -58,7 +60,7 @@ sub build_headers {
     $headers .= $chunk;
   }
 
-  return $headers;
+  $headers;
 }
 
 # "Aren't we forgetting the true meaning of Christmas?
@@ -66,11 +68,8 @@ sub build_headers {
 sub generate_body_chunk {
   my ($self, $offset) = @_;
 
-  # Delay
-  my $delay = delete $self->{_delay};
-
   # Callback
-  if (!$delay && !length $self->{_b2}) {
+  if (!delete $self->{_delay} && !length $self->{_b2}) {
     my $cb = delete $self->{_drain};
     $self->$cb($offset) if $cb;
   }
@@ -83,7 +82,7 @@ sub generate_body_chunk {
   # EOF or delay
   return $self->{_eof} ? '' : undef unless length $chunk;
 
-  return $chunk;
+  $chunk;
 }
 
 sub get_body_chunk {
@@ -95,53 +94,45 @@ sub get_header_chunk {
 
   # Normal headers
   my $copy = $self->{_b1} ||= $self->_build_headers;
-  return substr($copy, $offset, CHUNK_SIZE);
+  substr($copy, $offset, CHUNK_SIZE);
 }
 
 sub has_leftovers {
   my $self = shift;
-
-  # Leftovers
   return 1 if length $self->{_b2} || length $self->{_b1};
-
-  # Empty buffer
-  return;
+  undef;
 }
 
 sub header_size { length shift->build_headers }
 
 sub is_chunked {
   my $self = shift;
-
-  # Chunked
   my $encoding = $self->headers->transfer_encoding || '';
-  return $encoding =~ /chunked/i ? 1 : 0;
+  $encoding =~ /chunked/i ? 1 : 0;
 }
 
 sub is_done {
   return 1 if (shift->{_state} || '') eq 'done';
-  return;
+  undef;
 }
 
 sub is_dynamic {
   my $self = shift;
   return 1 if $self->on_read && !defined $self->headers->content_length;
-  return;
+  undef;
 }
 
 sub is_multipart {
   my $self = shift;
-
-  # Multipart
   my $type = $self->headers->content_type || '';
   $type =~ /multipart.*boundary=\"*([a-zA-Z0-9\'\(\)\,\.\:\?\-\_\+\/]+)/i
     and return $1;
-  return;
+  undef;
 }
 
 sub is_parsing_body {
   return 1 if (shift->{_state} || '') eq 'body';
-  return;
+  undef;
 }
 
 sub leftovers {
@@ -152,7 +143,7 @@ sub leftovers {
   return $self->{_b1} if length $self->{_b1};
 
   # Normal leftovers
-  return $self->{_b2};
+  $self->{_b2};
 }
 
 sub parse {
@@ -202,7 +193,7 @@ sub parse {
     # Normal content
     else {
 
-      # Need
+      # Bytes needed
       my $len = $self->headers->content_length || 0;
       $self->{_size} ||= 0;
       my $need = $len - $self->{_size};
@@ -219,7 +210,7 @@ sub parse {
     }
   }
 
-  return $self;
+  $self;
 }
 
 sub parse_body {
@@ -232,7 +223,7 @@ sub parse_body_once {
   my $self = shift;
   $self->parse_body(@_);
   $self->{_state} = 'done';
-  return $self;
+  $self;
 }
 
 # "Quick Smithers. Bring the mind eraser device!
@@ -264,7 +255,7 @@ sub parse_until_body {
   # Parse headers
   $self->_parse_headers if ($self->{_state} || '') eq 'headers';
 
-  return $self;
+  $self;
 }
 
 sub progress {
@@ -326,19 +317,14 @@ sub _build_chunk {
     $formatted .= sprintf('%x', length $chunk) . "\x0d\x0a$chunk";
   }
 
-  return $formatted;
+  $formatted;
 }
 
 sub _build_headers {
-  my $self = shift;
-
-  # Build
+  my $self    = shift;
   my $headers = $self->headers->to_string;
-
-  # Empty
   return "\x0d\x0a" unless $headers;
-
-  return "$headers\x0d\x0a\x0d\x0a";
+  "$headers\x0d\x0a\x0d\x0a";
 }
 
 sub _parse_chunked {
@@ -457,14 +443,14 @@ Try to detect broken web servers and turn on relaxed parsing automatically.
   my $headers = $content->headers;
   $content    = $content->headers(Mojo::Headers->new);
 
-The headers.
+Content headers, defaults to a L<Mojo::Headers> object.
 
 =head2 C<on_read>
 
   my $cb   = $content->on_read;
   $content = $content->on_read(sub {...});
 
-Content parser callback.
+Callback to be invoked when new content arrives.
 
   $content = $content->on_read(sub {
     my ($self, $chunk) = @_;
@@ -541,7 +527,7 @@ Size of headers in bytes.
 
   my $chunked = $content->is_chunked;
 
-Chunked transfer encoding.
+Check if content is chunked.
 
 =head2 C<is_done>
 
@@ -553,14 +539,14 @@ Check if parser is done.
 
   my $dynamic = $content->is_dynamic;
 
-Dynamic content.
+Check if content will be dynamic.
 Note that this method is EXPERIMENTAL and might change without warning!
 
 =head2 C<is_multipart>
 
   my $multipart = $content->is_multipart;
 
-Multipart content.
+Check if content is multipart.
 
 =head2 C<is_parsing_body>
 
@@ -572,25 +558,25 @@ Check if body parsing started yet.
 
   my $bytes = $content->leftovers;
 
-Leftovers for next HTTP message.
+Remove leftover data from content parser.
 
 =head2 C<parse>
 
   $content = $content->parse("Content-Length: 12\r\n\r\nHello World!");
 
-Parse content.
+Parse content chunk.
 
 =head2 C<parse_body>
 
   $content = $content->parse_body("Hi!");
 
-Parse body.
+Parse body chunk.
 
 =head2 C<parse_body_once>
 
   $content = $content->parse_body_once("Hi!");
 
-Parse body once.
+Parse body chunk once.
 
 =head2 C<parse_until_body>
 
@@ -598,7 +584,7 @@ Parse body once.
     "Content-Length: 12\r\n\r\nHello World!"
   );
 
-Parse and stop after headers.
+Parse chunk and stop after headers.
 
 =head2 C<progress>
 
@@ -9,14 +9,11 @@ use Mojo::Util 'unquote';
 sub parse {
   my ($self, $string) = @_;
 
+  # Walk tree
   my @cookies;
   my $version = 1;
-
-  # Walk tree
   for my $knot ($self->_tokenize($string)) {
     for my $token (@{$knot}) {
-
-      # Token
       my ($name, $value) = @{$token};
 
       # Value might be quoted
@@ -39,15 +36,13 @@ sub parse {
     }
   }
 
-  return \@cookies;
+  \@cookies;
 }
 
 sub prefix {
   my $self = shift;
-
-  # Prefix
   my $version = $self->version || 1;
-  return "\$Version=$version";
+  "\$Version=$version";
 }
 
 sub to_string {
@@ -60,7 +55,7 @@ sub to_string {
   $cookie .= "=$value" if defined $value && length $value;
   if (my $path = $self->path) { $cookie .= "; \$Path=$path" }
 
-  return $cookie;
+  $cookie;
 }
 
 sub to_string_with_prefix {
@@ -69,7 +64,7 @@ sub to_string_with_prefix {
   # Render with prefix
   my $prefix = $self->prefix;
   my $cookie = $self->to_string;
-  return "$prefix; $cookie";
+  "$prefix; $cookie";
 }
 
 1;
@@ -37,7 +37,7 @@ sub expires {
   $self->{expires} = Mojo::Date->new($self->{expires})
     unless ref $self->{expires};
 
-  return $self->{expires};
+  $self->{expires};
 }
 
 # "Remember the time he ate my goldfish?
@@ -45,8 +45,9 @@ sub expires {
 #  Then why did I have the bowl Bart? Why did I have the bowl?"
 sub parse {
   my ($self, $string) = @_;
-  my @cookies;
 
+  # Walk tree
+  my @cookies;
   for my $knot ($self->_tokenize($string)) {
     for my $i (0 .. $#{$knot}) {
       my ($name, $value) = @{$knot->[$i]};
@@ -74,7 +75,7 @@ sub parse {
     }
   }
 
-  return \@cookies;
+  \@cookies;
 }
 
 sub to_string {
@@ -115,7 +116,7 @@ sub to_string {
   # Comment
   if (my $comment = $self->comment) { $cookie .= "; Comment=$comment" }
 
-  return $cookie;
+  $cookie;
 }
 
 1;
@@ -31,12 +31,12 @@ sub to_string { croak 'Method "to_string" not implemented by subclass' }
 sub _tokenize {
   my ($self, $string) = @_;
 
+  # Nibbling parser
   my (@tree, @token);
   while ($string) {
 
     # Name
     if ($string =~ s/$NAME_RE//o) {
-
       my $name = $1;
       my $value;
 
@@ -67,7 +67,7 @@ sub _tokenize {
   # No separator
   push @tree, [@token] if @token;
 
-  return @tree;
+  @tree;
 }
 
 1;
@@ -16,8 +16,6 @@ sub add {
 
   # Add cookies
   for my $cookie (@cookies) {
-
-    # Unique cookie id
     my $domain = $cookie->domain;
     my $path   = $cookie->path;
     my $name   = $cookie->name;
@@ -28,27 +26,23 @@ sub add {
     # Default to session cookie
     $cookie->max_age(0) unless $cookie->expires || $cookie->max_age;
 
-    # Cookie too big
+    # Check cookie size
     my $value = $cookie->value;
     next if length(defined $value ? $value : '') > $self->max_cookie_size;
 
-    # Initialize
-    $self->{_jar}->{$domain} ||= [];
-
     # Check if we already have a similar cookie
+    $self->{_jar}->{$domain} ||= [];
     my @new;
     for my $old (@{$self->{_jar}->{$domain}}) {
-
-      # Unique cookie id
       push @new, $old unless $old->path eq $path && $old->name eq $name;
     }
 
-    # Add
+    # Yummy!
     push @new, $cookie;
     $self->{_jar}->{$domain} = \@new;
   }
 
-  return $self;
+  $self;
 }
 
 sub empty { shift->{_jar} = {} }
@@ -56,16 +50,12 @@ sub empty { shift->{_jar} = {} }
 sub extract {
   my ($self, $tx) = @_;
 
-  # Fix cookies
+  # Repair cookies and put them in the jar
   my $url     = $tx->req->url;
   my @cookies = @{$tx->res->cookies};
   for my $cookie (@cookies) {
-
-    # Domain
     $cookie->domain($url->host) unless $cookie->domain;
-
-    # Path
-    $cookie->path($url->path) unless $cookie->path;
+    $cookie->path($url->path)   unless $cookie->path;
   }
   $self->add(@cookies);
 }
@@ -73,40 +63,28 @@ sub extract {
 sub find {
   my ($self, $url) = @_;
 
-  # Pattern
+  # Look through the jar
   return unless my $domain = $url->host;
   my $path = $url->path->to_string || '/';
-
-  # Find
   my @found;
   while ($domain =~ /[^\.]+\.[^\.]+|localhost$/) {
-
-    # Nothing
     next unless my $jar = $self->{_jar}->{$domain};
 
-    # Look inside
+    # Grab cookies
     my @new;
     for my $cookie (@$jar) {
 
-      # Session cookie
+      # Check if cookie has expired
       my $session = defined $cookie->max_age && $cookie->max_age > 0 ? 1 : 0;
-      if ($cookie->expires && !$session) {
-
-        # Expired
-        next if time > ($cookie->expires->epoch || 0);
+      if ((my $expires = $cookie->expires) && !$session) {
+        next if time > ($expires->epoch || 0);
       }
-
-      # Not expired
       push @new, $cookie;
 
-      # Port
+      # Taste cookie
       my $port = $url->port || 80;
       next if $cookie->port && $port != $cookie->port;
-
-      # Protocol
       next if $cookie->secure && $url->scheme ne 'https';
-
-      # Path
       my $cpath = $cookie->path;
       push @found,
         Mojo::Cookie::Request->new(
@@ -117,22 +95,21 @@ sub find {
         secure  => $cookie->secure
         ) if $path =~ /^$cpath/;
     }
+
     $self->{_jar}->{$domain} = \@new;
   }
 
-  # Remove leading dot or part
-  continue { $domain =~ s/^(?:\.|[^\.]+)// }
+  # Remove another part
+  continue { $domain =~ s/^(?:\.?[^\.]+)// }
 
-  return @found;
+  @found;
 }
 
 sub inject {
   my ($self, $tx) = @_;
 
-  # Empty jar
+  # Take delicious cookies from the jar
   return unless keys %{$self->{_jar}};
-
-  # Fetch
   my $req = $tx->req;
   my $url = $req->url->clone;
   if (my $host = $req->headers->host) { $url->host($host) }
@@ -153,7 +130,8 @@ Mojo::CookieJar - Cookie Jar For HTTP 1.1 User Agents
 
 =head1 DESCRIPTION
 
-L<Mojo::CookieJar> is a minimalistic cookie jar for HTTP 1.1 user agents.
+L<Mojo::CookieJar> is a minimalistic and relaxed cookie jar for HTTP 1.1 user
+agents.
 
 =head1 ATTRIBUTES
 
@@ -156,7 +156,7 @@ sub new {
   # Parse right away
   $self->parse($xml) if defined $xml;
 
-  return $self;
+  $self;
 }
 
 # DEPRECATED in Smiling Face With Sunglasses!
@@ -186,6 +186,7 @@ sub all_text {
   while (my $e = shift @stack) {
     my $type = $e->[0];
 
+    # Add children of nested tag to stack
     unshift @stack, @$e[4 .. $#$e] and next if $type eq 'tag';
 
     # Text
@@ -201,7 +202,7 @@ sub all_text {
     $text .= $content if $content =~ /\S+/;
   }
 
-  return $text;
+  $text;
 }
 
 sub append { shift->_add(1, @_) }
@@ -210,7 +211,7 @@ sub append_content {
   my ($self, $new) = @_;
   my $tree = $self->tree;
   push @$tree, @{_parent($self->_parse_xml("$new"), $tree->[3])};
-  return $self;
+  $self;
 }
 
 sub at { shift->find(@_)->[0] }
@@ -235,14 +236,14 @@ sub attrs {
     $attrs->{$key} = $values->{$key};
   }
 
-  return $self;
+  $self;
 }
 
 sub charset {
   my $self = shift;
   return $self->[1] if @_ == 0;
   $self->[1] = shift;
-  return $self;
+  $self;
 }
 
 # "Oh boy! Sleep! That's when I'm a Viking!"
@@ -255,7 +256,7 @@ sub children {
   my $start = $tree->[0] eq 'root' ? 1 : 4;
   for my $e (@$tree[$start .. $#$tree]) {
 
-    # Tag
+    # Make sure child is a tag
     next unless $e->[0] eq 'tag';
     next if defined $type && $e->[1] ne $type;
 
@@ -264,20 +265,17 @@ sub children {
       $self->new(charset => $self->charset, tree => $e, xml => $self->xml);
   }
 
-  # Collection
-  return bless \@children, 'Mojo::DOM::_Collection';
+  bless \@children, 'Mojo::DOM::_Collection';
 }
 
 sub content_xml {
   my $self = shift;
 
   # Walk tree
-  my $tree   = $self->tree;
   my $result = '';
+  my $tree   = $self->tree;
   my $start  = $tree->[0] eq 'root' ? 1 : 4;
   for my $e (@$tree[$start .. $#$tree]) {
-
-    # Render
     $result .= $self->_render($e);
   }
 
@@ -285,17 +283,12 @@ sub content_xml {
   my $charset = $self->charset;
   encode $charset, $result if $charset;
 
-  return $result;
+  $result;
 }
 
 sub find {
   my ($self, $css) = @_;
-
-  # Parse CSS selectors
-  my $pattern = $self->_parse_css($css);
-
-  # Filter tree
-  return $self->_match_tree($self->tree, $pattern);
+  $self->_match_tree($self->tree, $self->_parse_css($css));
 }
 
 # DEPRECATED in Smiling Face With Sunglasses!
@@ -309,17 +302,15 @@ EOF
 sub namespace {
   my $self = shift;
 
+  # Prefix
   my $current = $self->tree;
   return if $current->[0] eq 'root';
-
-  # Prefix
   my $prefix = '';
   if ($current->[1] =~ /^(.*?)\:/) { $prefix = $1 }
 
   # Walk tree
   while ($current) {
     return if $current->[0] eq 'root';
-
     my $attrs = $current->[2];
 
     # Namespace for prefix
@@ -355,11 +346,7 @@ sub parent {
 
 sub parse {
   my ($self, $xml) = @_;
-
-  # Detect Perl characters
   $self->charset(undef) if utf8::is_utf8 $xml;
-
-  # Parse
   $self->tree($self->_parse_xml($xml));
 }
 
@@ -370,7 +357,7 @@ sub prepend_content {
   my $tree = $self->tree;
   splice @$tree, $tree->[0] eq 'root' ? 1 : 4, 0,
     @{_parent($self->_parse_xml("$new"), $tree->[3])};
-  return $self;
+  $self;
 }
 
 sub replace {
@@ -393,7 +380,7 @@ sub replace {
   # Replace
   splice @$parent, $i, 1, @{_parent($new, $parent)};
 
-  return $self;
+  $self;
 }
 
 sub replace_content {
@@ -414,7 +401,7 @@ sub replace_content {
   my $start = $tree->[0] eq 'root' ? 1 : 4;
   splice @$tree, $start, $#$tree, @new;
 
-  return $self;
+  $self;
 }
 
 # DEPRECATED in Smiling Face With Sunglasses!
@@ -446,14 +433,10 @@ sub root {
 sub text {
   my $self = shift;
 
-  my $text = '';
-
   # Walk stack
+  my $text = '';
   for my $e (@{$self->tree}) {
-
-    # Meta data
     next unless ref $e eq 'ARRAY';
-
     my $type = $e->[0];
 
     # Text
@@ -469,27 +452,22 @@ sub text {
     $text .= $content if $content =~ /\S+/;
   }
 
-  return $text;
+  $text;
 }
 
 sub to_xml {
-  my $self = shift;
-
-  # Render
-  my $result = $self->_render($self->tree);
-
-  # Encode
+  my $self    = shift;
+  my $result  = $self->_render($self->tree);
   my $charset = $self->charset;
   encode $charset, $result if $charset;
-
-  return $result;
+  $result;
 }
 
 sub tree {
   my $self = shift;
   return $self->[0] if @_ == 0;
   $self->[0] = shift;
-  return $self;
+  $self;
 }
 
 sub type {
@@ -505,14 +483,14 @@ sub type {
   # Set
   $tree->[1] = $type;
 
-  return $self;
+  $self;
 }
 
 sub xml {
   my $self = shift;
   return $self->[2] if @_ == 0;
   $self->[2] = shift;
-  return $self;
+  $self;
 }
 
 sub _add {
@@ -536,7 +514,7 @@ sub _add {
   # Add
   splice @$parent, $i + $offset, 0, @{_parent($new, $parent)};
 
-  return $self;
+  $self;
 }
 
 # "Woah! God is so in your face!
@@ -548,22 +526,18 @@ sub _cdata {
 
 sub _close {
   my ($self, $current, $tags, $stop) = @_;
-
-  # Default to table tags
   $tags ||= \%HTML_TABLE;
-
-  # Default to table tag
   $stop ||= 'table';
 
-  # Check parents
+  # Check if parents need to be closed
   my $parent = $$current;
   while ($parent) {
     last if $parent->[0] eq 'root' || $parent->[1] eq $stop;
 
-    # Match
+    # Close
     $tags->{$parent->[1]} and $self->_end($parent->[1], $current);
 
-    # Next
+    # Try next
     $parent = $parent->[3];
   }
 }
@@ -575,9 +549,9 @@ sub _comment {
 
 sub _css_equation {
   my ($self, $equation) = @_;
-  my $num = [1, 1];
 
   # "even"
+  my $num = [1, 1];
   if ($equation =~ /^even$/i) { $num = [2, 2] }
 
   # "odd"
@@ -592,18 +566,16 @@ sub _css_equation {
     $num->[1] =~ s/\s+//g;
   }
 
-  return $num;
+  $num;
 }
 
 sub _css_regex {
   my ($self, $op, $value) = @_;
-
   return unless $value;
   $value = quotemeta $self->_css_unescape($value);
 
-  my $regex;
-
   # "~=" (word)
+  my $regex;
   if ($op eq '~') { $regex = qr/(?:^|.*\s+)$value(?:\s+.*|$)/ }
 
   # "*=" (contains)
@@ -618,7 +590,7 @@ sub _css_regex {
   # Everything else
   else { $regex = qr/^$value$/ }
 
-  return $regex;
+  $regex;
 }
 
 sub _css_unescape {
@@ -633,7 +605,7 @@ sub _css_unescape {
   # Remove backslash
   $value =~ s/\\//g;
 
-  return $value;
+  $value;
 }
 
 sub _doctype {
@@ -643,7 +615,6 @@ sub _doctype {
 
 sub _end {
   my ($self, $end, $current) = @_;
-
   warn "END $end\n" if DEBUG;
 
   # Not a tag
@@ -655,7 +626,7 @@ sub _end {
   while ($next) {
     last if $next->[0] eq 'root';
 
-    # Found
+    # Right tag
     ++$found and last if $next->[1] eq $end;
 
     # Don't cross block tags that are not optional tags
@@ -664,6 +635,7 @@ sub _end {
         && $HTML_BLOCK{$next->[1]}
         && !$HTML_OPTIONAL{$next->[1]};
 
+    # Parent
     $next = $next->[3];
   }
 
@@ -695,21 +667,18 @@ sub _end {
 sub _match_element {
   my ($self, $candidate, $selectors) = @_;
 
+  # Match
   my @selectors  = reverse @$selectors;
   my $first      = 2;
   my $parentonly = 0;
   my $tree       = $self->tree;
   my ($current, $marker, $snapback, $siblings);
-
-  # Match
   for (my $i = 0; $i <= $#selectors; $i++) {
     my $selector = $selectors[$i];
 
     # Combinator
     $parentonly-- if $parentonly > 0;
     if ($selector->[0] eq 'combinator') {
-
-      # Combinator
       my $c = $selector->[1];
 
       # Parent only ">"
@@ -798,7 +767,7 @@ sub _match_element {
     }
   }
 
-  return 1;
+  1;
 }
 
 sub _match_selector {
@@ -882,10 +851,8 @@ sub _match_selector {
         $args = $c->[2] = $self->_css_equation($args)
           unless ref $args;
 
-        # Parent
-        my $parent = $current->[3];
-
         # Siblings
+        my $parent = $current->[3];
         my $start = $parent->[0] eq 'root' ? 1 : 4;
         my @siblings;
         my $type = $class =~ /of-type$/ ? $current->[1] : undef;
@@ -917,10 +884,8 @@ sub _match_selector {
       elsif ($class =~ /^only-(?:child|(of-type))$/) {
         my $type = $1 ? $current->[1] : undef;
 
-        # Parent
-        my $parent = $current->[3];
-
         # Siblings
+        my $parent = $current->[3];
         my $start = $parent->[0] eq 'root' ? 1 : 4;
         for my $j ($start .. $#$parent) {
           my $sibling = $parent->[$j];
@@ -938,7 +903,7 @@ sub _match_selector {
     return;
   }
 
-  return 1;
+  1;
 }
 
 sub _match_tree {
@@ -966,8 +931,6 @@ sub _match_tree {
 
       # Parts
       for my $part (@$pattern) {
-
-        # Match
         push(@results, $current) and last
           if $self->_match_element($current, $part);
       }
@@ -979,8 +942,7 @@ sub _match_tree {
     $self->new(charset => $self->charset, tree => $_, xml => $self->xml)
   } @results;
 
-  # Collection
-  return bless \@results, 'Mojo::DOM::_Collection';
+  bless \@results, 'Mojo::DOM::_Collection';
 }
 
 sub _parent {
@@ -990,7 +952,7 @@ sub _parent {
     $e->[3] = $parent if $e->[0] eq 'tag';
     push @new, $e;
   }
-  return \@new;
+  \@new;
 }
 
 sub _parse_css {
@@ -1064,22 +1026,19 @@ sub _parse_css {
     push @$part, ['combinator', $combinator] if $combinator;
   }
 
-  return $pattern;
+  $pattern;
 }
 
 sub _parse_xml {
   my ($self, $xml) = @_;
 
-  # State
-  my $tree    = ['root'];
-  my $current = $tree;
-
   # Decode
   my $charset = $self->charset;
   decode $charset, $xml if $charset && !utf8::is_utf8 $xml;
-  return $tree unless $xml;
 
   # Tokenize
+  my $tree    = ['root'];
+  my $current = $tree;
   while ($xml =~ m/\G$XML_TOKEN_RE/gcs) {
     my $text    = $1;
     my $pi      = $2;
@@ -1090,10 +1049,7 @@ sub _parse_xml {
 
     # Text
     if (length $text) {
-
-      # Unescape
       html_unescape $text if (index $text, '&') >= 0;
-
       $self->_text($text, \$current);
     }
 
@@ -1132,13 +1088,11 @@ sub _parse_xml {
         $value = $3 unless defined $value;
         $value = $4 unless defined $value;
 
-        # End
+        # Empty tag
         next if $key eq '/';
 
-        # Unescape
+        # Add unescaped value
         html_unescape $value if $value && (index $value, '&') >= 0;
-
-        # Merge
         $attrs->{$key} = $value;
       }
 
@@ -1159,15 +1113,13 @@ sub _parse_xml {
     }
   }
 
-  return $tree;
+  $tree;
 }
 
+# Try to detect XML from processing instructions
 sub _pi {
   my ($self, $pi, $current) = @_;
-
-  # Try to detect XML
   $self->xml(1) if !defined $self->xml && $pi =~ /xml/i;
-
   push @$$current, ['pi', $pi];
 }
 
@@ -1179,9 +1131,8 @@ sub _raw {
 sub _render {
   my ($self, $tree) = @_;
 
-  my $e = $tree->[0];
-
   # Text (escaped)
+  my $e = $tree->[0];
   if ($e eq 'text') {
     my $escaped = $tree->[1];
     xml_escape $escaped;
@@ -1206,9 +1157,8 @@ sub _render {
   # Offset
   my $start = $e eq 'root' ? 1 : 2;
 
-  my $content = '';
-
   # Start tag
+  my $content = '';
   if ($e eq 'tag') {
 
     # Offset
@@ -1225,10 +1175,8 @@ sub _render {
       # No value
       push @attrs, $key and next unless defined $value;
 
-      # Escape
-      xml_escape $value;
-
       # Key and value
+      xml_escape $value;
       push @attrs, qq/$key="$value"/;
     }
     my $attrs = join ' ', @attrs;
@@ -1242,23 +1190,18 @@ sub _render {
   }
 
   # Walk tree
-  for my $i ($start .. $#$tree) {
-
-    # Render next element
-    $content .= $self->_render($tree->[$i]);
-  }
+  $content .= $self->_render($tree->[$_]) for $start .. $#$tree;
 
   # End tag
   $content .= '</' . $tree->[1] . '>' if $e eq 'tag';
 
-  return $content;
+  $content;
 }
 
 # "It's not important to talk about who got rich off of whom,
 #  or who got exposed to tainted what..."
 sub _start {
   my ($self, $start, $attrs, $current) = @_;
-
   warn "START $start\n" if DEBUG;
 
   # Autoclose optional HTML tags
@@ -1336,10 +1279,10 @@ sub _trim {
   $text =~ s/\s*\n+\s*$//;
   $text =~ s/\s*\n+\s*/\ /g;
 
-  # Add leading whitespace
-  $text = " $text" if $ws;
+  # Add leading whitespace if punctuation allows it
+  $text = " $text" if $ws && $text =~ /^[^\.\!\?\,\;\:]/;
 
-  return $text;
+  $text;
 }
 
 # "Hi, Super Nintendo Chalmers!"
@@ -1364,7 +1307,7 @@ sub _iterate {
 
   # Root
   return unless my $start = $self->[0];
-  return $start->root;
+  $start->root;
 }
 
 1;
@@ -12,8 +12,6 @@ has 'epoch';
 # Days and months
 my @DAYS   = qw/Sun Mon Tue Wed Thu Fri Sat/;
 my @MONTHS = qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/;
-
-# Reverse months
 my %MONTHS;
 {
   my $i = 0;
@@ -26,7 +24,7 @@ my %MONTHS;
 sub new {
   my $self = shift->SUPER::new();
   $self->parse(@_);
-  return $self;
+  $self;
 }
 
 # "I suggest you leave immediately.
@@ -35,7 +33,6 @@ sub new {
 #  at you?"
 sub parse {
   my ($self, $date) = @_;
-
   return $self unless defined $date;
 
   # epoch - 784111777
@@ -51,9 +48,8 @@ sub parse {
   $date =~ s/GMT\s*$//i;
   $date =~ s/\s+$//;
 
+  # RFC 822/1123 - Sun, 06 Nov 1994 08:49:37 GMT
   my ($day, $month, $year, $hour, $minute, $second);
-
-  # RFC822/1123 - Sun, 06 Nov 1994 08:49:37 GMT
   if ($date =~ /^(\d+)\s+(\w+)\s+(\d+)\s+(\d+):(\d+):(\d+)$/) {
     $day    = $1;
     $month  = $MONTHS{$2};
@@ -63,7 +59,7 @@ sub parse {
     $second = $6;
   }
 
-  # RFC850/1036 - Sunday, 06-Nov-94 08:49:37 GMT
+  # RFC 850/1036 - Sunday, 06-Nov-94 08:49:37 GMT
   elsif ($date =~ /^(\d+)-(\w+)-(\d+)\s+(\d+):(\d+):(\d+)$/) {
     $day    = $1;
     $month  = $MONTHS{$2};
@@ -95,17 +91,16 @@ sub parse {
   return $self if $@ || $epoch < 0;
   $self->epoch($epoch);
 
-  return $self;
+  $self;
 }
 
 sub to_string {
   my $self = shift;
 
+  # RFC 822/1123
   my $epoch = $self->epoch;
   $epoch = time unless defined $epoch;
   my ($second, $minute, $hour, $mday, $month, $year, $wday) = gmtime $epoch;
-
-  # Format
   return sprintf(
     "%s, %02d %s %04d %02d:%02d:%02d GMT",
     $DAYS[$wday], $mday, $MONTHS[$month], $year + 1900,
@@ -21,7 +21,7 @@ sub new {
   return $self unless @_;
 
   # Detect
-  return $self->_detect(@_);
+  $self->_detect(@_);
 }
 
 sub throw {
@@ -49,7 +49,7 @@ sub trace {
   }
   $e->frames(\@frames);
 
-  return $e;
+  $e;
 }
 
 sub _detect {
@@ -129,7 +129,7 @@ sub _detect {
   # Context
   $self->_parse_context($line, \@lines) if $line;
 
-  return $self;
+  $self;
 }
 
 # "You killed zombie Flanders!
@@ -140,9 +140,8 @@ sub to_string {
   # Message only
   return $self->message unless $self->verbose;
 
+  # Start with message
   my $string = '';
-
-  # Message
   $string .= $self->message if $self->message;
 
   # Before
@@ -159,7 +158,7 @@ sub to_string {
     $string .= $line->[0] . ': ' . $line->[1] . "\n";
   }
 
-  return $string;
+  $string;
 }
 
 sub _parse_context {
@@ -208,7 +207,7 @@ sub _parse_context {
     }
   }
 
-  return $self;
+  $self;
 }
 
 1;
@@ -99,7 +99,7 @@ sub add {
   push @{$self->{_headers}->{$name}}, (ref $_ || '') eq 'ARRAY' ? $_ : [$_]
     for @_;
 
-  return $self;
+  $self;
 }
 
 sub connection          { scalar shift->header(Connection            => @_) }
@@ -132,7 +132,7 @@ sub from_hash {
     $self->add($header => ref $value eq 'ARRAY' ? @$value : $value);
   }
 
-  return $self;
+  $self;
 }
 
 # "Will you be my mommy? You smell like dead bunnies..."
@@ -152,7 +152,7 @@ sub header {
   return join ', ', map { join ', ', @$_ } @$headers unless wantarray;
 
   # Array
-  return @$headers;
+  @$headers;
 }
 
 sub host { scalar shift->header(Host => @_) }
@@ -177,21 +177,18 @@ sub names {
     push @headers, $NORMALCASE_HEADERS{$name} || $name;
   }
 
-  return \@headers;
+  \@headers;
 }
 
 sub parse {
   my ($self, $chunk) = @_;
 
+  # Parse headers with size limit
+  $self->{_state} = 'headers';
   $self->{_buffer} = '' unless defined $self->{_buffer};
   $self->{_buffer} .= $chunk if defined $chunk;
-
-  # Maximum line size
-  my $max = $self->max_line_size;
-
-  # Parse headers
   my $headers = $self->{_cache} || [];
-  $self->{_state} = 'headers';
+  my $max = $self->max_line_size;
   while (defined(my $line = get_line $self->{_buffer})) {
 
     # Check line size
@@ -233,7 +230,7 @@ sub parse {
     $self->{_limit} = 1;
   }
 
-  return $self;
+  $self;
 }
 
 sub proxy_authenticate  { scalar shift->header('Proxy-Authenticate'  => @_) }
@@ -244,7 +241,7 @@ sub referrer            { scalar shift->header(Referer               => @_) }
 sub remove {
   my ($self, $name) = @_;
   delete $self->{_headers}->{lc $name};
-  return $self;
+  $self;
 }
 
 sub sec_websocket_accept {
@@ -291,7 +288,7 @@ sub to_hash {
     }
   }
 
-  return $hash;
+  $hash;
 }
 
 sub to_string {
@@ -310,7 +307,7 @@ sub to_string {
 
   # Format headers
   my $headers = join "\x0d\x0a", @headers;
-  return length $headers ? $headers : undef;
+  length $headers ? $headers : undef;
 }
 
 sub trailer           { scalar shift->header(Trailer             => @_) }
@@ -17,7 +17,7 @@ sub new {
   $self->log->level('error');
   $self->log->path(undef);
 
-  return $self;
+  $self;
 }
 
 sub handler {
@@ -222,11 +222,8 @@ EOF
 sub _upload {
   my ($self, $tx) = @_;
 
-  # Code
-  my $res = $tx->res;
-  $res->code(200);
-
   # File
+  my $res = $tx->res;
   my $req = $tx->req;
   if (my $file = $req->upload('file')) {
     my $headers = $res->headers;
@@ -255,6 +252,9 @@ sub _upload {
 </html>
 EOF
   }
+
+  # Response
+  $res->code(200);
   $tx->resume;
 }
 
@@ -283,8 +283,14 @@ sub _websocket {
   <head>
     <title>Mojo Diagnostics</title>
     <script language="javascript">
-      if ("WebSocket" in window) {
+      var ws;
+      if ("MozWebSocket" in window) {
+        ws = new MozWebSocket("$url");
+      }
+      else if ("WebSocket" in window) {
         ws = new WebSocket("$url");
+      }
+      if(typeof(ws) !== 'undefined') {
         function wsmessage(event) {
           data = event.data;
           alert(data);
@@ -60,7 +60,7 @@ sub detect {
   # FindBin fallback
   $self->{_parts} = [split /\//, $FindBin::Bin] unless $self->{_parts};
 
-  return $self;
+  $self;
 }
 
 sub lib_dir {
@@ -72,12 +72,13 @@ sub lib_dir {
   return $path if -d $path;
 
   # No lib directory
-  return;
+  undef;
 }
 
 sub list_files {
   my ($self, $dir) = @_;
 
+  # Build portable directory
   my $parts = $self->{_parts} || [];
   my $root = File::Spec->catdir(@$parts);
   $dir = File::Spec->catdir($root, split '/', ($dir || ''));
@@ -108,7 +109,7 @@ sub list_files {
     push @files, @$new;
   }
 
-  return [sort @files];
+  [sort @files];
 }
 
 # "And now to create an unstoppable army of between one million and two
@@ -117,25 +118,25 @@ sub parse {
   my ($self, $path) = @_;
   my @parts = File::Spec->splitdir($path);
   $self->{_parts} = \@parts;
-  return $self;
+  $self;
 }
 
 sub rel_dir {
   my $self = shift;
   my $parts = $self->{_parts} || [];
-  return File::Spec->catdir(@$parts, split '/', shift);
+  File::Spec->catdir(@$parts, split '/', shift);
 }
 
 sub rel_file {
   my $self = shift;
   my $parts = $self->{_parts} || [];
-  return File::Spec->catfile(@$parts, split '/', shift);
+  File::Spec->catfile(@$parts, split '/', shift);
 }
 
 sub to_string {
   my $self = shift;
   my $parts = $self->{_parts} || [];
-  return File::Spec->catdir(@$parts);
+  File::Spec->catdir(@$parts);
 }
 
 1;
@@ -192,7 +192,7 @@ sub new {
   # Ignore PIPE signal
   $SIG{PIPE} = 'IGNORE';
 
-  return $self;
+  $self;
 }
 
 sub connect {
@@ -234,14 +234,14 @@ sub connect {
   # Connect
   else { $self->_connect($id, $args) }
 
-  return $id;
+  $id;
 }
 
 sub connection_timeout {
   my ($self, $id, $timeout) = @_;
   return unless my $c = $self->{_cs}->{$id};
   $c->{timeout} = $timeout and return $self if $timeout;
-  return $c->{timeout};
+  $c->{timeout};
 }
 
 sub dns_servers {
@@ -260,7 +260,7 @@ sub dns_servers {
 
   # Current server
   $CURRENT_DNS_SERVER = 0 unless $DNS_SERVERS->[$CURRENT_DNS_SERVER];
-  return $DNS_SERVERS->[$CURRENT_DNS_SERVER];
+  $DNS_SERVERS->[$CURRENT_DNS_SERVER];
 }
 
 sub drop {
@@ -270,8 +270,8 @@ sub drop {
   # Drop connection gracefully
   if (my $c = $self->{_cs}->{$id}) { return $c->{finish} = 1 }
 
-  # Drop
-  return $self->_drop_immediately($id);
+  # Drop right away
+  $self->_drop_immediately($id);
 }
 
 sub generate_port {
@@ -290,7 +290,7 @@ sub generate_port {
       );
   }
 
-  return;
+  undef;
 }
 
 sub idle {
@@ -312,19 +312,13 @@ sub listen {
   $self = $self->singleton unless ref $self;
   my $args = ref $_[0] ? $_[0] : {@_};
 
+  # No TLS support
   croak "IO::Socket::SSL 1.43 required for TLS support"
     if $args->{tls} && !TLS;
 
-  my %options = (
-    Listen => $args->{backlog} || SOMAXCONN,
-    Proto  => 'tcp',
-    Type   => SOCK_STREAM,
-    %{$args->{args} || {}}
-  );
-  my $file = $args->{file};
-  my $port = $args->{port} || 3000;
-
   # File descriptor reuse
+  my $file  = $args->{file};
+  my $port  = $args->{port} || 3000;
   my $reuse = defined $file ? $file : $port;
   $ENV{MOJO_REUSE} ||= '';
   my $fd;
@@ -338,6 +332,12 @@ sub listen {
 
   # Listen on UNIX domain socket
   my $socket;
+  my %options = (
+    Listen => $args->{backlog} || SOMAXCONN,
+    Proto  => 'tcp',
+    Type   => SOCK_STREAM,
+    %{$args->{args} || {}}
+  );
   if (defined $file) {
     $options{Local} = $file;
     $socket =
@@ -410,20 +410,19 @@ sub listen {
   # Accept limit
   $self->{_accepts} = $self->max_accepts if $self->max_accepts;
 
-  return $id;
+  $id;
 }
 
 sub local_info {
   my ($self, $id) = @_;
 
+  # UNIX domain socket info
   return {} unless my $c      = $self->{_cs}->{$id};
   return {} unless my $socket = $c->{handle};
-
-  # UNIX domain socket info
   return {path => $socket->hostpath} if $socket->can('hostpath');
 
-  # Info
-  return {address => $socket->sockhost, port => $socket->sockport};
+  # TCP socket info
+  {address => $socket->sockhost, port => $socket->sockport};
 }
 
 sub lookup {
@@ -476,20 +475,17 @@ sub one_tick {
   my ($self, $timeout) = @_;
   $timeout = $self->timeout unless defined $timeout;
 
+  # Housekeeping
   $self->_prepare_listen;
   $self->_prepare_connections;
+  my $loop = $self->_prepare_loop;
 
-  my $loop  = $self->_prepare_loop;
+  # KQueue
   my $r     = $self->{_reverse};
   my $ready = {};
-
-  # KQueue
   if (KQUEUE) {
-
-    # Catch interrupted system call errors
     my @ret;
-    my $success = eval { @ret = $loop->kevent(1000 * $timeout); 1 };
-    die "KQueue error: $@" if !$success && $@;
+    eval { @ret = $loop->kevent(1000 * $timeout) };
 
     # Events
     for my $kev (@ret) {
@@ -543,35 +539,30 @@ sub one_tick {
 sub handle {
   my ($self, $id) = @_;
   return unless my $c = $self->{_cs}->{$id};
-  return $c->{handle};
+  $c->{handle};
 }
 
 sub remote_info {
   my ($self, $id) = @_;
 
+  # UNIX domain socket info
   return {} unless my $c      = $self->{_cs}->{$id};
   return {} unless my $socket = $c->{handle};
-
-  # UNIX domain socket info
   return {path => $socket->peerpath} if $socket->can('peerpath');
 
-  # Info
-  return {address => $socket->peerhost, port => $socket->peerport};
+  # TCP socket info
+  {address => $socket->peerhost, port => $socket->peerport};
 }
 
 sub resolve {
   my ($self, $name, $type, $cb) = @_;
   $self = $self->singleton unless ref $self;
 
-  my $ipv4;
-  $ipv4 = 1 if $name =~ $Mojo::URL::IPV4_RE;
-  my $ipv6;
-  $ipv6 = 1 if IPV6_DNS && $name =~ $Mojo::URL::IPV6_RE;
-
+  # No lookup required or record type not supported
+  my $ipv4 = $name =~ $Mojo::URL::IPV4_RE ? 1 : 0;
+  my $ipv6   = IPV6_DNS && $name =~ $Mojo::URL::IPV6_RE ? 1 : 0;
   my $t      = $DNS_TYPES->{$type};
   my $server = $self->dns_servers;
-
-  # No lookup required or record type not supported
   if (!$server || !$t || ($t ne $DNS_TYPES->{PTR} && ($ipv4 || $ipv6))) {
     $self->timer(0 => sub { $self->$cb([]) });
     return $self;
@@ -610,15 +601,12 @@ sub resolve {
         $req .= pack 'C/a*', $part if defined $part;
       }
       $req .= pack 'Cnn', 0, $t, 0x0001;
-
       $self->write($id => $req);
     },
     on_error => sub {
       my ($self, $id) = @_;
-
       warn "FAILED $type $name ($server)\n" if DEBUG;
       $CURRENT_DNS_SERVER++;
-
       $self->drop($timer) if $timer;
       $self->$cb([]);
     },
@@ -629,15 +617,13 @@ sub resolve {
       $self->drop($id);
       $self->drop($timer) if $timer;
 
+      # Check answers
       my @packet = unpack 'nnnnnna*', $chunk;
       warn "ANSWERS $packet[3] ($server)\n" if DEBUG;
-
-      # Wrong response
       return $self->$cb([]) unless $packet[0] eq $tx;
 
-      my $content = $packet[6];
-
       # Questions
+      my $content = $packet[6];
       for (1 .. $packet[2]) {
         my $n;
         do { ($n, $content) = unpack 'C/aa*', $content } while ($n ne '');
@@ -660,7 +646,6 @@ sub resolve {
         push @answers, [@answer, $ttl];
         warn "ANSWER $answer[0] $answer[1]\n" if DEBUG;
       }
-
       $self->$cb(\@answers);
     }
   );
@@ -669,17 +654,16 @@ sub resolve {
   $timer = $self->timer(
     $self->dns_timeout => sub {
       my $self = shift;
-
       warn "RESOLVE TIMEOUT ($server)\n" if DEBUG;
-      $CURRENT_DNS_SERVER++;
 
       # Abort
+      $CURRENT_DNS_SERVER++;
       $self->drop($id);
       $self->$cb([]);
     }
   );
 
-  return $self;
+  $self;
 }
 
 sub singleton { $LOOP ||= shift->new(@_) }
@@ -695,12 +679,13 @@ sub start {
   # Mainloop
   $self->one_tick while $self->{_running};
 
-  return $self;
+  $self;
 }
 
 sub start_tls {
   my $self = shift;
   my $id   = shift;
+  my $args = ref $_[0] ? $_[0] : {@_};
 
   # No TLS support
   unless (TLS) {
@@ -708,24 +693,9 @@ sub start_tls {
     return;
   }
 
-  my $args = ref $_[0] ? $_[0] : {@_};
-  weaken $self;
-  my %options = (
-    SSL_startHandshake => 0,
-    SSL_error_trap     => sub { $self->_error($id, $_[1]) },
-    SSL_cert_file      => $args->{tls_cert},
-    SSL_key_file       => $args->{tls_key},
-    SSL_verify_mode    => 0x00,
-    SSL_create_ctx_callback =>
-      sub { Net::SSLeay::CTX_sess_set_cache_size(shift, 128) },
-    Timeout => $self->connect_timeout,
-    %{$args->{tls_args} || {}}
-  );
-
+  # Cleanup
   $self->drop($id) and return unless my $c      = $self->{_cs}->{$id};
   $self->drop($id) and return unless my $socket = $c->{handle};
-
-  # Cleanup
   my $fd = fileno $socket;
   delete $self->{_reverse}->{$socket};
   my $writing = delete $c->{writing};
@@ -737,6 +707,18 @@ sub start_tls {
   else { $loop->remove($socket) if defined $writing }
 
   # TLS upgrade
+  weaken $self;
+  my %options = (
+    SSL_startHandshake => 0,
+    SSL_error_trap     => sub { $self->_error($id, $_[1]) },
+    SSL_cert_file      => $args->{tls_cert},
+    SSL_key_file       => $args->{tls_key},
+    SSL_verify_mode    => 0x00,
+    SSL_create_ctx_callback =>
+      sub { Net::SSLeay::CTX_sess_set_cache_size(shift, 128) },
+    Timeout => $self->connect_timeout,
+    %{$args->{tls_args} || {}}
+  );
   $self->drop($id) and return
     unless my $new = IO::Socket::SSL->start_SSL($socket, %options);
   $c->{handle} = $new;
@@ -744,7 +726,7 @@ sub start_tls {
   $c->{tls_connect} = 1;
   $self->_writing($id);
 
-  return $id;
+  $id;
 }
 
 sub stop {
@@ -756,17 +738,16 @@ sub stop {
 sub test {
   my ($self, $id) = @_;
 
+  # Handle is tainted if readable
   return unless my $c      = $self->{_cs}->{$id};
   return unless my $socket = $c->{handle};
-
-  # Test
   my $test = $self->{_test} ||= IO::Poll->new;
   $test->mask($socket, POLLIN);
   $test->poll(0);
   my $result = $test->handles(POLLIN | POLLERR | POLLHUP);
   $test->remove($socket);
 
-  return !$result;
+  !$result;
 }
 
 sub timer {
@@ -778,6 +759,7 @@ sub timer {
 sub write {
   my ($self, $id, $chunk, $cb) = @_;
 
+  # Prepare chunk for writing
   my $c = $self->{_cs}->{$id};
   $c->{buffer} .= $chunk;
 
@@ -850,7 +832,7 @@ sub _add_event {
   my ($self, $event, $id, $cb) = @_;
   return unless my $c = $self->{_cs}->{$id};
   $c->{$event} = $cb if $cb;
-  return $self;
+  $self;
 }
 
 sub _add_loop_event {
@@ -862,14 +844,13 @@ sub _add_loop_event {
   (my $id) = "$e" =~ /0x([\da-f]+)/;
   $self->{"_$event"}->{$id} = $e;
 
-  return $id;
+  $id;
 }
 
 sub _connect {
   my ($self, $id, $args) = @_;
 
-  return unless my $c = $self->{_cs}->{$id};
-
+  # Default socket options
   my %options = (
     Blocking => 0,
     PeerAddr => $args->{address},
@@ -881,6 +862,7 @@ sub _connect {
 
   # Handle
   my $handle;
+  return unless my $c = $self->{_cs}->{$id};
   unless ($handle = $args->{handle} || $args->{socket}) {
 
     # IPv6
@@ -974,7 +956,7 @@ sub _drop_immediately {
     close $handle;
   }
 
-  return $self;
+  $self;
 }
 
 sub _error {
@@ -1017,6 +999,7 @@ sub _not_listening {
 sub _not_writing {
   my ($self, $id) = @_;
 
+  # Make sure the handle is ready
   return unless my $c = $self->{_cs}->{$id};
   return $c->{read_only} = 1 if length $c->{buffer} || $c->{drain};
   return unless my $handle = $c->{handle};
@@ -1039,7 +1022,6 @@ sub _not_writing {
       $loop->remove($handle);
       $writing = undef;
     }
-
     my $mask = EPOLL ? EPOLL_POLLIN : POLLIN;
     $loop->mask($handle, $mask) unless defined $writing;
   }
@@ -1086,7 +1068,7 @@ sub _parse_answer {
   return $type => _parse_name($packet, $offset) if $type;
 
   # Not supported
-  return;
+  undef;
 }
 
 # Domain name helper for "resolve"
@@ -1115,12 +1097,13 @@ sub _parse_name {
     else { return join '.', @elements }
   }
 
-  return;
+  undef;
 }
 
 sub _prepare_cert {
   my $self = shift;
 
+  # Check if temporary TLS cert file already exists
   my $cert = $self->{_cert};
   return $cert if $cert && -r $cert;
 
@@ -1132,15 +1115,14 @@ sub _prepare_cert {
     or croak qq/Can't create temporary TLS cert file "$cert"/;
   print $file CERT;
 
-  return $self->{_cert} = $cert;
+  $self->{_cert} = $cert;
 }
 
 sub _prepare_connections {
   my $self = shift;
 
-  my $cs = $self->{_cs} ||= {};
-
   # Prepare
+  my $cs = $self->{_cs} ||= {};
   while (my ($id, $c) = each %$cs) {
 
     # Connection needs to be finished
@@ -1168,6 +1150,7 @@ sub _prepare_connections {
 sub _prepare_key {
   my $self = shift;
 
+  # Check if temporary TLS key file already exists
   my $key = $self->{_key};
   return $key if $key && -r $key;
 
@@ -1179,7 +1162,7 @@ sub _prepare_key {
     or croak qq/Can't create temporary TLS key file "$key"/;
   print $file KEY;
 
-  return $self->{_key} = $key;
+  $self->{_key} = $key;
 }
 
 sub _prepare_listen {
@@ -1237,7 +1220,7 @@ sub _prepare_loop {
     $self->{_loop} = IO::Poll->new;
   }
 
-  return $self->{_loop};
+  $self->{_loop};
 }
 
 sub _read {
@@ -1289,16 +1272,16 @@ sub _run_callback {
   my $value = eval { $self->$cb(@_) };
   warn qq/Callback "$event" failed: $@/ if $@;
 
-  return $value;
+  $value;
 }
 
-# Failed events should not kill everything
 sub _run_event {
   my $self  = shift;
   my $event = shift;
   my $cb    = shift;
   my $id    = shift;
 
+  # Failed events should not kill everything
   my $value = eval { $self->$cb($id, @_) };
   if ($@) {
     my $message = qq/Event "$event" failed for connection "$id": $@/;
@@ -1307,7 +1290,7 @@ sub _run_event {
       : $self->_error($id, $message);
   }
 
-  return $value;
+  $value;
 }
 
 sub _timer {
@@ -1338,7 +1321,7 @@ sub _timer {
     }
   }
 
-  return $count;
+  $count;
 }
 
 sub _tls_accept {
@@ -1355,7 +1338,7 @@ sub _tls_accept {
     return;
   }
 
-  # Handle error
+  # Switch between reading and writing
   $self->_tls_error($id);
 }
 
@@ -1373,18 +1356,14 @@ sub _tls_connect {
     return;
   }
 
-  # Handle error
+  # Switch between reading and writing
   $self->_tls_error($id);
 }
 
 sub _tls_error {
   my ($self, $id) = @_;
   my $error = $IO::Socket::SSL::SSL_ERROR;
-
-  # Reading
-  if ($error == TLS_READ) { $self->_not_writing($id) }
-
-  # Writing
+  if    ($error == TLS_READ)  { $self->_not_writing($id) }
   elsif ($error == TLS_WRITE) { $self->_writing($id) }
 }
 
@@ -1796,7 +1775,7 @@ A unix domain socket to listen on.
 
 =item C<on_accept>
 
-Callback to invoke for each accepted connection.
+Callback to be invoked for each accepted connection.
 
 =item C<on_close>
 
@@ -110,14 +110,14 @@ sub decode {
     $self->error($e);
   }
 
-  return $res;
+  $res;
 }
 
 sub encode {
   my ($self, $ref) = @_;
   my $string = _encode_values($ref);
   Mojo::Util::encode 'UTF-8', $string;
-  return $string;
+  $string;
 }
 
 sub false {$FALSE}
@@ -140,7 +140,7 @@ sub _decode_array {
     _exception('Expected comma or right square bracket while parsing array');
   }
 
-  return \@array;
+  \@array;
 }
 
 sub _decode_object {
@@ -171,13 +171,13 @@ sub _decode_object {
     _exception(q/Expected comma or right curly bracket while parsing object/);
   }
 
-  return \%hash;
+  \%hash;
 }
 
 sub _decode_string {
   my $pos = pos;
 
-  # String
+  # Extract string with escaped characters
   m/\G(((?:[^\x00-\x1F\\"]|\\(?:["\\\/bfnrt]|u[A-Fa-f0-9]{4})){0,32766})*)/gc;
   my $str = $1;
 
@@ -188,13 +188,13 @@ sub _decode_string {
     _exception('Unterminated string');
   }
 
-  # Popular characters
+  # Unescape popular characters
   if (index($str, '\\u') < 0) {
     $str =~ s/\\(["\\\/bfnrt])/$ESCAPE{$1}/gs;
     return $str;
   }
 
-  # Everything else
+  # Unescape everything else
   my $buffer = '';
   while ($str =~ m/\G([^\\]*)\\(?:([^u])|u(.{4}))/gc) {
     $buffer .= $1;
@@ -231,7 +231,7 @@ sub _decode_string {
   # The rest
   $buffer .= substr $str, pos($str), length($str);
 
-  return $buffer;
+  $buffer;
 }
 
 # "Eternity with nerds.
@@ -278,7 +278,7 @@ sub _encode_array {
 
   # Stringify
   my $string = join ',', @array;
-  return "[$string]";
+  "[$string]";
 }
 
 sub _encode_object {
@@ -294,18 +294,18 @@ sub _encode_object {
 
   # Stringify
   my $string = join ',', @values;
-  return "{$string}";
+  "{$string}";
 }
 
 sub _encode_string {
   my $string = shift;
 
-  # Escape
+  # Escape string
   $string
     =~ s/([\x00-\x1F\x7F\x{2028}\x{2029}\\\"\/\b\f\n\r\t])/$REVERSE{$1}/gs;
 
   # Stringify
-  return "\"$string\"";
+  "\"$string\"";
 }
 
 sub _encode_values {
@@ -336,7 +336,7 @@ sub _encode_values {
     if $flags & (B::SVp_IOK | B::SVp_NOK) && !($flags & B::SVp_POK);
 
   # String
-  return _encode_string($value);
+  _encode_string($value);
 }
 
 sub _exception {
@@ -383,7 +383,7 @@ Mojo::JSON - Minimalistic JSON
 
 =head1 DESCRIPTION
 
-L<Mojo::JSON> is a minimalistic and relaxed implementation of RFC4627.
+L<Mojo::JSON> is a minimalistic and relaxed implementation of RFC 4627.
 While it is possibly the fastest pure-Perl JSON parser available, you should
 not use it for validation.
 
@@ -1,20 +1,15 @@
 package Mojo::Loader;
 use Mojo::Base -base;
 
+# "Don't let Krusty's death get you down, boy.
+#  People die all the time, just like that.
+#  Why, you could wake up dead tomorrow! Well, good night."
 use Carp 'carp';
 use File::Basename;
 use File::Spec;
 use Mojo::Command;
 use Mojo::Exception;
 
-use constant DEBUG => $ENV{MOJO_LOADER_DEBUG} || 0;
-
-# Cache stats
-my $STATS = {};
-
-# Debugger sub tracking
-BEGIN { $^P |= 0x10 }
-
 # "Homer no function beer well without."
 sub load {
   my ($self, $module) = @_;
@@ -22,16 +17,8 @@ sub load {
   # Check module name
   return 1 if !$module || $module !~ /^[\w\:\']+$/;
 
-  # Forced reload
-  if ($ENV{MOJO_RELOAD}) {
-    my $key = $module;
-    $key =~ s/\:\:/\//g;
-    $key .= '.pm';
-    _unload($key);
-  }
-
   # Already loaded
-  else { return if $module->can('new') }
+  return if $module->can('new');
 
   # Load
   unless (eval "require $module; 1") {
@@ -44,40 +31,11 @@ sub load {
     return Mojo::Exception->new($@);
   }
 
-  return;
-}
-
-# "Don't let Krusty's death get you down, boy.
-#  People die all the time, just like that.
-#  Why, you could wake up dead tomorrow! Well, good night."
-sub reload {
-
-  # Cleanup script and "main" namespace
-  delete $INC{$0};
-  $STATS->{$0} = 1;
-  _purge(grep { index($_, 'main::') == 0 } keys %DB::sub);
-
-  # Reload
-  while (my ($key, $file) = each %INC) {
-
-    # Modified time
-    next unless $file;
-    my $mtime = (stat $file)[9];
-
-    # Startup time as default
-    $STATS->{$file} = $^T unless defined $STATS->{$file};
-
-    # Modified
-    if ($mtime > $STATS->{$file}) {
-      if (my $e = _reload($key)) { return $e }
-      $STATS->{$file} = $mtime;
-    }
-  }
-
-  # Force script reloading
-  return _reload($0);
+  undef;
 }
 
+# "This is the worst thing you've ever done.
+#  You say that so often that it lost its meaning."
 sub search {
   my ($self, $namespace) = @_;
 
@@ -95,12 +53,9 @@ sub search {
 
     # Check files
     for my $file (@files) {
-      my $full = File::Spec->catfile(File::Spec->splitdir($path), $file);
+      next if -d File::Spec->catfile(File::Spec->splitdir($path), $file);
 
-      # Directory
-      next if -d $full;
-
-      # Found
+      # Module found
       my $name = File::Basename::fileparse($file, qr/\.pm/);
       my $class = "$namespace\::$name";
       push @$modules, $class unless $found{$class};
@@ -109,36 +64,7 @@ sub search {
   }
 
   return unless @$modules;
-  return $modules;
-}
-
-# "This is the worst thing you've ever done.
-#  You say that so often that it lost its meaning."
-sub _purge {
-  for my $sub (@_) {
-    warn "PURGE $sub\n" if DEBUG;
-    carp "Can't unload sub '$sub': $@" unless eval { undef &$sub; 1 };
-    delete $DB::sub{$sub};
-    no strict 'refs';
-    $sub =~ /^(.*::)(.*?)$/ and delete *{$1}->{$2};
-  }
-}
-
-sub _reload {
-  my $key = shift;
-  return if $key eq 'Mojo/Loader.pm';
-  warn "CLEANING $key\n" if DEBUG;
-  _unload($key);
-  warn "RELOADING $key\n" if DEBUG;
-  return Mojo::Exception->new($@)
-    unless eval { package main; require $key; 1 };
-  return;
-}
-
-sub _unload {
-  my $key = shift;
-  return unless my $file = delete $INC{$key};
-  _purge(grep { index($DB::sub{$_}, "$file:") == 0 } keys %DB::sub);
+  $modules;
 }
 
 1;
@@ -156,9 +82,6 @@ Mojo::Loader - Loader
   my $modules = $loader->search('Some::Namespace');
   $loader->load($modules->[0]);
 
-  # Reload
-  Mojo::Loader->reload;
-
 =head1 DESCRIPTION
 
 L<Mojo::Loader> is a class loader and plugin framework.
@@ -172,27 +95,21 @@ following new ones.
 
   my $e = $loader->load('Foo::Bar');
 
-Load a class, note that classes are checked for a C<new> method to see if
-they are already loaded.
-
-=head2 C<reload>
+Load a class and catch exceptions.
+Note that classes are checked for a C<new> method to see if they are already
+loaded.
 
-  my $e = Mojo::Loader->reload;
-
-Reload all Perl files with changes.
+  if (my $e = $loader->load('Foo::Bar')) {
+    die "Exception: $e" if ref $e;
+  }
 
 =head2 C<search>
 
   my $modules = $loader->search('MyApp::Namespace');
 
-Search modules in a namespace.
-
-=head1 DEBUGGING
-
-You can set the C<MOJO_LOADER_DEBUG> environment variable to get some
-advanced diagnostics information printed to C<STDERR>.
+Search for modules in a namespace non-recursively.
 
-  MOJO_LOADER_DEBUG=1
+  $loader->load($_) for @{$loader->search('MyApp::Namespace')};
 
 =head1 SEE ALSO
 
@@ -20,11 +20,12 @@ has handle => sub {
   $file->open(">> $path") or croak qq/Can't open log file "$path": $!/;
   binmode $file, ':utf8';
 
-  return $file;
+  $file;
 };
 has level => 'debug';
 has 'path';
 
+# Supported log level
 my $LEVEL = {debug => 1, info => 2, warn => 3, error => 4, fatal => 5};
 
 # "Yes, I got the most! I win X-Mas!"
@@ -43,7 +44,7 @@ sub is_level {
   return unless $level;
   $level = lc $level;
   my $current = $ENV{MOJO_LOG_LEVEL} || $self->level;
-  return $LEVEL->{$level} >= $LEVEL->{$current};
+  $LEVEL->{$level} >= $LEVEL->{$current};
 }
 
 sub is_warn { shift->is_level('warn') }
@@ -57,10 +58,6 @@ sub log {
   $level = lc $level;
   return $self unless $level && $self->is_level($level);
 
-  my $time = localtime(time);
-  my $msgs = join "\n",
-    map { utf8::decode $_ unless utf8::is_utf8 $_; $_ } @msgs;
-
   # Caller
   my ($pkg, $line) = (caller())[0, 2];
   ($pkg, $line) = (caller(1))[0, 2] if $pkg eq ref $self;
@@ -69,13 +66,16 @@ sub log {
   my $handle = $self->handle;
   flock $handle, LOCK_EX;
 
-  # Log message
+  # Log messages
+  my $time = localtime(time);
+  my $msgs = join "\n",
+    map { utf8::decode $_ unless utf8::is_utf8 $_; $_ } @msgs;
   $handle->syswrite("$time $level $pkg:$line [$$]: $msgs\n");
 
   # Unlock
   flock $handle, LOCK_UN;
 
-  return $self;
+  $self;
 }
 
 sub warn { shift->log('warn', @_) }
@@ -49,7 +49,7 @@ sub cookies {
   }
 
   # No cookies
-  return [];
+  [];
 }
 
 sub fix_headers {
@@ -80,39 +80,35 @@ sub fix_headers {
     }
   }
 
-  return $self;
+  $self;
 }
 
 sub is_secure {
-  my $self = shift;
-
-  # Secure
-  my $url = $self->url;
+  my $self   = shift;
+  my $url    = $self->url;
   my $scheme = $url->scheme || $url->base->scheme || '';
   return 1 if $scheme eq 'https';
-
-  # Not secure
-  return;
+  undef;
 }
 
 sub is_xhr {
   my $self = shift;
   return unless my $with = $self->headers->header('X-Requested-With');
   return 1 if $with =~ /XMLHttpRequest/i;
-  return;
+  undef;
 }
 
 sub param {
   my $self = shift;
   $self->{_params} = $self->params unless $self->{_params};
-  return $self->{_params}->param(@_);
+  $self->{_params}->param(@_);
 }
 
 sub params {
   my $self   = shift;
   my $params = Mojo::Parameters->new;
   $params->merge($self->body_params, $self->query_params);
-  return $params;
+  $params;
 }
 
 sub parse {
@@ -174,7 +170,7 @@ sub parse {
     }
   }
 
-  return $self;
+  $self;
 }
 
 sub proxy {
@@ -192,7 +188,7 @@ sub proxy {
     return $self;
   }
 
-  return $self->{proxy};
+  $self->{proxy};
 }
 
 sub query_params { shift->url->query }
@@ -229,7 +225,7 @@ sub _build_start_line {
   return "$method $path\x0d\x0a" if $version eq '0.9';
 
   # HTTP 1.0 and above
-  return "$method $path HTTP/$version\x0d\x0a";
+  "$method $path HTTP/$version\x0d\x0a";
 }
 
 sub _parse_basic_auth {
@@ -237,7 +233,7 @@ sub _parse_basic_auth {
   return unless $header =~ /Basic (.+)$/;
   my $auth = $1;
   b64_decode $auth;
-  return $auth;
+  $auth;
 }
 
 sub _parse_env {
@@ -247,11 +243,10 @@ sub _parse_env {
   # Make environment accessible
   $self->env($env);
 
+  # Extract headers from environment
   my $headers = $self->headers;
   my $url     = $self->url;
   my $base    = $url->base;
-
-  # Extract headers from environment
   for my $name (keys %$env) {
 
     # Header
@@ -389,13 +384,19 @@ Mojo::Message::Request - HTTP 1.1 Request Container
 
   use Mojo::Message::Request;
 
+  # Parse
+  my $req = Mojo::Message::Request->new;
+  $req->parse("GET /foo HTTP/1.0\x0a\x0d");
+  $req->parse("Content-Length: 12\x0a\x0d\x0a\x0d");
+  $req->parse("Content-Type: text/plain\x0a\x0d\x0a\x0d");
+  $req->parse('Hello World!');
+  print $req->body;
+
+  # Build
   my $req = Mojo::Message::Request->new;
   $req->url->parse('http://127.0.0.1/foo/bar');
   $req->method('GET');
-
-  print "$req";
-
-  $req->parse('GET /foo/bar HTTP/1.1');
+  print $req->to_string;
 
 =head1 DESCRIPTION
 
@@ -421,18 +422,6 @@ Direct access to the environment hash if available.
 
 HTTP request method.
 
-=head2 C<params>
-
-  my $params = $req->params;
-
-All C<GET> and C<POST> parameters, defaults to a L<Mojo::Parameters> object.
-
-=head2 C<query_params>
-
-  my $params = $req->query_params;
-
-All C<GET> parameters, defaults to a L<Mojo::Parameters> object.
-
 =head2 C<url>
 
   my $url = $req->url;
@@ -451,7 +440,7 @@ implements the following new ones.
   $req        = $req->cookies(Mojo::Cookie::Request->new);
   $req        = $req->cookies({name => 'foo', value => 'bar'});
 
-Access request cookies.
+Access request cookies, usually L<Mojo::Cookie::Request> objects.
 
 =head2 C<fix_headers>
 
@@ -475,8 +464,13 @@ Check C<X-Requested-With> header for C<XMLHttpRequest> value.
 
   my $param = $req->param('foo');
 
-Access C<GET> and C<POST> parameters, defaults to a L<Mojo::Parameters>
-object.
+Access C<GET> and C<POST> parameters.
+
+=head2 C<params>
+
+  my $params = $req->params;
+
+All C<GET> and C<POST> parameters, usually a L<Mojo::Parameters> object.
 
 =head2 C<parse>
 
@@ -494,6 +488,12 @@ Parse HTTP request chunks or environment hash.
 
 Proxy URL for message.
 
+=head2 C<query_params>
+
+  my $params = $req->query_params;
+
+All C<GET> parameters, usually a L<Mojo::Parameters> object.
+
 =head1 SEE ALSO
 
 L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicio.us>.
@@ -101,7 +101,7 @@ sub cookies {
   }
 
   # No cookies
-  return $cookies;
+  $cookies;
 }
 
 sub default_message { $MESSAGES{$_[1] || $_[0]->code || 404} || '' }
@@ -114,29 +114,27 @@ sub fix_headers {
   my $headers = $self->headers;
   $headers->date(Mojo::Date->new->to_string) unless $headers->date;
 
-  return $self;
+  $self;
 }
 
 sub is_status_class {
   my ($self, $class) = @_;
   return unless my $code = $self->code;
   return 1 if $code >= $class && $code < ($class + 100);
-  return;
+  undef;
 }
 
 sub _build_start_line {
   my $self = shift;
 
-  # Version
-  my $version = $self->version;
-
   # HTTP 0.9 has no start line
+  my $version = $self->version;
   return '' if $version eq '0.9';
 
   # HTTP 1.0 and above
   my $code    = $self->code    || 404;
   my $message = $self->message || $self->default_message;
-  return "HTTP/$version $code $message\x0d\x0a";
+  "HTTP/$version $code $message\x0d\x0a";
 }
 
 # "Weaseling out of things is important to learn.
@@ -190,14 +188,20 @@ Mojo::Message::Response - HTTP 1.1 Response Container
 
   use Mojo::Message::Response;
 
+  # Parse
+  my $res = Mojo::Message::Reponse->new;
+  $res->parse("HTTP/1.0 200 OK\x0a\x0d");
+  $res->parse("Content-Length: 12\x0a\x0d\x0a\x0d");
+  $res->parse("Content-Type: text/plain\x0a\x0d\x0a\x0d");
+  $res->parse('Hello World!');
+  print $res->body;
+
+  # Build
   my $res = Mojo::Message::Response->new;
   $res->code(200);
   $res->headers->content_type('text/plain');
   $res->body('Hello World!');
-
-  print "$res";
-
-  $res->parse('HTTP/1.1 200 OK');
+  print $res->to_string;
 
 =head1 DESCRIPTION
 
@@ -234,7 +238,7 @@ implements the following new ones.
   $res        = $res->cookies(Mojo::Cookie::Response->new);
   $req        = $req->cookies({name => 'foo', value => 'bar'});
 
-Access response cookies.
+Access response cookies, usually L<Mojo::Cookie::Response> objects.
 
 =head2 C<default_message>
 
@@ -4,7 +4,8 @@ use Mojo::Base -base;
 use Carp 'croak';
 use Mojo::Asset::Memory;
 use Mojo::Content::Single;
-use Mojo::Loader;
+use Mojo::DOM;
+use Mojo::JSON;
 use Mojo::Parameters;
 use Mojo::Upload;
 use Mojo::Util qw/decode url_unescape/;
@@ -35,7 +36,7 @@ sub at_least_version {
     if $search_major == $current_major && $search_minor <= $current_minor;
 
   # Version is older
-  return;
+  undef;
 }
 
 sub body {
@@ -64,7 +65,7 @@ sub body {
   # Set text content
   elsif (length $new) { $content->asset->add_chunk($new) }
 
-  return $self;
+  $self;
 }
 
 sub body_params {
@@ -73,10 +74,9 @@ sub body_params {
   # Cached
   return $self->{_body_params} if $self->{_body_params};
 
+  # Charset
   my $params = Mojo::Parameters->new;
   my $type = $self->headers->content_type || '';
-
-  # Charset
   $params->charset($self->default_charset);
   $type =~ /charset=\"?(\S+)\"?/ and $params->charset($1);
 
@@ -98,12 +98,13 @@ sub body_params {
       # File
       next if $filename;
 
+      # Form value
       $params->append($name, $value);
     }
   }
 
   # Cache
-  return $self->{_body_params} = $params;
+  $self->{_body_params} = $params;
 }
 
 sub body_size { shift->content->body_size }
@@ -117,7 +118,7 @@ sub build_body {
   my $body = $self->content->build_body(@_);
   $self->{_state} = 'done';
   if (my $cb = $self->on_finish) { $self->$cb }
-  return $body;
+  $body;
 }
 
 sub build_headers {
@@ -127,7 +128,7 @@ sub build_headers {
   return '' if $self->version eq '0.9';
 
   $self->fix_headers;
-  return $self->content->build_headers;
+  $self->content->build_headers;
 }
 
 sub build_start_line {
@@ -149,7 +150,7 @@ sub build_start_line {
     $startline .= $chunk;
   }
 
-  return $startline;
+  $startline;
 }
 
 sub cookie {
@@ -182,8 +183,7 @@ sub cookie {
   my @cookies;
   @cookies = ref $cookies eq 'ARRAY' ? @$cookies : ($cookies) if $cookies;
 
-  # Context
-  return wantarray ? @cookies : $cookies[0];
+  wantarray ? @cookies : $cookies[0];
 }
 
 sub dom {
@@ -192,26 +192,18 @@ sub dom {
   # Multipart
   return if $self->is_multipart;
 
-  # Load DOM class
-  my $class = $self->dom_class;
-  if (my $e = Mojo::Loader->load($class)) {
-    croak ref $e
-      ? qq/Can't load DOM class "$class": $e/
-      : qq/DOM class "$class" doesn't exist./;
-  }
-
   # Charset
   my $charset;
   ($self->headers->content_type || '') =~ /charset=\"?([^\"\s;]+)\"?/
     and $charset = $1;
 
   # Parse
-  my $dom = $class->new(charset => $charset)->parse($self->body);
+  my $dom = $self->dom_class->new(charset => $charset)->parse($self->body);
 
   # Find right away
   return $dom->find(@_) if @_;
 
-  return $dom;
+  $dom;
 }
 
 sub error {
@@ -227,7 +219,7 @@ sub error {
   $self->{_error} = [@_];
   $self->{_state} = 'done';
 
-  return $self;
+  $self;
 }
 
 sub fix_headers {
@@ -244,7 +236,7 @@ sub fix_headers {
     }
   }
 
-  return $self;
+  $self;
 }
 
 sub get_body_chunk {
@@ -261,7 +253,7 @@ sub get_body_chunk {
   $self->{_state} = 'done';
   if (my $cb = $self->on_finish) { $self->$cb }
 
-  return $chunk;
+  $chunk;
 }
 
 sub get_header_chunk {
@@ -273,7 +265,7 @@ sub get_header_chunk {
   # HTTP 0.9 has no headers
   return '' if $self->version eq '0.9';
 
-  return $self->content->get_header_chunk(@_);
+  $self->content->get_header_chunk(@_);
 }
 
 sub get_start_line_chunk {
@@ -284,7 +276,7 @@ sub get_start_line_chunk {
 
   # Get chunk
   my $copy = $self->{_buffer} ||= $self->_build_start_line;
-  return substr $copy, $offset, CHUNK_SIZE;
+  substr $copy, $offset, CHUNK_SIZE;
 }
 
 sub has_leftovers { shift->content->has_leftovers }
@@ -292,7 +284,7 @@ sub has_leftovers { shift->content->has_leftovers }
 sub header_size {
   my $self = shift;
   $self->fix_headers;
-  return $self->content->header_size;
+  $self->content->header_size;
 }
 
 sub headers {
@@ -305,14 +297,14 @@ sub headers {
   }
 
   # Get
-  return $self->content->headers(@_);
+  $self->content->headers(@_);
 }
 
 sub is_chunked { shift->content->is_chunked }
 
 sub is_done {
   return 1 if (shift->{_state} || '') eq 'done';
-  return;
+  undef;
 }
 
 sub is_dynamic { shift->content->is_dynamic }
@@ -321,27 +313,15 @@ sub is_limit_exceeded {
   my $self = shift;
   return unless my $code = ($self->error)[1];
   return unless $code eq '413';
-  return 1;
+  1;
 }
 
 sub is_multipart { shift->content->is_multipart }
 
 sub json {
   my $self = shift;
-
-  # Multipart
   return if $self->is_multipart;
-
-  # Load JSON class
-  my $class = $self->json_class;
-  if (my $e = Mojo::Loader->load($class)) {
-    croak ref $e
-      ? qq/Can't load JSON class "$class": $e/
-      : qq/JSON class "$class" doesn't exist./;
-  }
-
-  # Decode
-  return $class->new->decode($self->body);
+  $self->json_class->new->decode($self->body);
 }
 
 sub leftovers { shift->content->leftovers }
@@ -351,7 +331,7 @@ sub max_line_size { shift->headers->max_line_size(@_) }
 sub param {
   my $self = shift;
   $self->{body_params} ||= $self->body_params;
-  return $self->{body_params}->param(@_);
+  $self->{body_params}->param(@_);
 }
 
 sub parse            { shift->_parse(0, @_) }
@@ -361,12 +341,11 @@ sub start_line_size { length shift->build_start_line }
 
 sub to_string {
   my $self = shift;
-  return $self->build_start_line . $self->build_headers . $self->build_body;
+  $self->build_start_line . $self->build_headers . $self->build_body;
 }
 
 sub upload {
   my ($self, $name) = @_;
-
   return unless $name;
 
   # Map
@@ -395,35 +374,36 @@ sub upload {
   my @uploads;
   @uploads = ref $uploads eq 'ARRAY' ? @$uploads : ($uploads) if $uploads;
 
-  return wantarray ? @uploads : $uploads[0];
+  wantarray ? @uploads : $uploads[0];
 }
 
 sub uploads {
   my $self = shift;
 
+  # Only multipart messages have uplaods
   my @uploads;
   return \@uploads unless $self->is_multipart;
 
+  # Extract formdata
   my $formdata = $self->_parse_formdata;
-
-  # Formdata
   for my $data (@$formdata) {
     my $name     = $data->[0];
     my $filename = $data->[1];
     my $part     = $data->[2];
 
+    # Just a form value
     next unless $filename;
 
+    # Uploaded file
     my $upload = Mojo::Upload->new;
     $upload->name($name);
     $upload->asset($part->asset);
     $upload->filename($filename);
     $upload->headers($part->headers);
-
     push @uploads, $upload;
   }
 
-  return \@uploads;
+  \@uploads;
 }
 
 sub write       { shift->content->write(@_) }
@@ -504,7 +484,7 @@ sub _parse {
   # Finished
   if ((my $cb = $self->on_finish) && $self->is_done) { $self->$cb }
 
-  return $self;
+  $self;
 }
 
 sub _parse_start_line {
@@ -514,9 +494,8 @@ sub _parse_start_line {
 sub _parse_formdata {
   my $self = shift;
 
-  my @formdata;
-
   # Check content
+  my @formdata;
   my $content = $self->content;
   return \@formdata unless $content->is_multipart;
 
@@ -564,8 +543,6 @@ sub _parse_formdata {
 
     # Form value
     unless ($filename) {
-
-      # Slurp
       $value = $part->asset->slurp;
 
       # Decode
@@ -579,7 +556,7 @@ sub _parse_formdata {
     push @formdata, [$name, $filename, $value];
   }
 
-  return \@formdata;
+  \@formdata;
 }
 
 1;
@@ -614,22 +591,23 @@ Content container, defaults to a L<Mojo::Content::Single> object.
   my $charset = $message->default_charset;
   $message    = $message->default_charset('UTF-8');
 
-Default charset used for form data parsing.
+Default charset used for form data parsing, defaults to C<UTF-8>.
 
 =head2 C<dom_class>
 
   my $class = $message->dom_class;
   $message  = $message->dom_class('Mojo::DOM');
 
-Class to be used for DOM manipulation, defaults to L<Mojo::DOM>.
+Class to be used for DOM manipulation with the C<dom> method, defaults to
+L<Mojo::DOM>.
 
 =head2 C<json_class>
 
   my $class = $message->json_class;
   $message  = $message->json_class('Mojo::JSON');
 
-Class to be used for JSON deserialization with C<json>, defaults to
-L<Mojo::JSON>.
+Class to be used for JSON deserialization with the C<json> method, defaults
+to L<Mojo::JSON>.
 
 =head2 C<max_message_size>
 
@@ -645,7 +623,7 @@ Maximum message size in bytes, defaults to C<5242880>.
     my $self = shift;
   });
 
-Callback called after message building or parsing is finished.
+Callback to be invoked after message building or parsing is finished.
 
 =head2 C<on_progress>
 
@@ -655,7 +633,7 @@ Callback called after message building or parsing is finished.
     print '+';
   });
 
-Progress callback.
+Callback to be invoked on progress.
 
 =head1 METHODS
 
@@ -674,13 +652,13 @@ Check if message is at least a specific version.
   $message   = $message->body('Hello!');
   $message   = $message->body(sub {...});
 
-Helper for simplified content access.
+Simple C<content> access.
 
 =head2 C<body_params>
 
   my $params = $message->body_params;
 
-C<POST> parameters.
+C<POST> parameters, usually a L<Mojo::Parameters> object.
 
 =head2 C<body_size>
 
@@ -711,7 +689,8 @@ Render start line.
   my $cookie  = $message->cookie('foo');
   my @cookies = $message->cookie('foo');
 
-Access message cookies.
+Access message cookies, usually L<Mojo::Cookie::Request> or
+L<Mojo::Cookie::Response> objects.
 
 =head2 C<dom>
 
@@ -771,7 +750,7 @@ Size of headers in bytes.
   my $headers = $message->headers;
   $message    = $message->headers(Mojo::Headers->new);
 
-Header container, defaults to a L<Mojo::Headers> object.
+Message headers, defaults to a L<Mojo::Headers> object.
 
 =head2 C<is_chunked>
 
@@ -817,7 +796,7 @@ C<undef> otherwise.
 
   my $bytes = $message->leftovers;
 
-Remove leftover data.
+Remove leftover data from message parser.
 
 =head2 C<max_line_size>
 
@@ -831,7 +810,7 @@ Note that this method is EXPERIMENTAL and might change without warning!
   my $param  = $message->param('foo');
   my @params = $message->param('foo');
 
-Access C<GET> and C<POST> parameters.
+Access C<GET> and C<POST> parameters>.
 
 =head2 C<parse>
 
@@ -862,13 +841,13 @@ Render whole message.
   my $upload  = $message->upload('foo');
   my @uploads = $message->upload('foo');
 
-Access file uploads.
+Access file uploads, usually L<Mojo::Upload> objects.
 
 =head2 C<uploads>
 
   my $uploads = $message->uploads;
 
-All file uploads.
+All file uploads, usually L<Mojo::Upload> objects.
 
 =head2 C<version>
 
@@ -10,7 +10,6 @@ use Mojo::URL;
 
 has charset        => 'UTF-8';
 has pair_separator => '&';
-has params         => sub { [] };
 
 # "Yeah, Moe, that team sure did suck last night. They just plain sucked!
 #  I've seen teams suck before,
@@ -24,9 +23,9 @@ sub new {
   if (@_ > 1) { $self->append(@_) }
 
   # String
-  else { $self->parse(@_) }
+  else { $self->{_string} = $_[0] }
 
-  return $self;
+  $self;
 }
 
 sub append {
@@ -40,21 +39,22 @@ sub append {
   }
   push @{$self->params}, map { defined $_ ? "$_" : '' } @params;
 
-  return $self;
+  $self;
 }
 
 sub clone {
   my $self  = shift;
   my $clone = Mojo::Parameters->new;
   $clone->pair_separator($self->pair_separator);
-  $clone->params([@{$self->params}]);
-  return $clone;
+  if (defined $self->{_string}) { $clone->{_string} = $self->{_string} }
+  else                          { $clone->params([@{$self->params}]) }
+  $clone;
 }
 
 sub merge {
   my $self = shift;
   push @{$self->params}, @{$_->params} for @_;
-  return $self;
+  $self;
 }
 
 sub param {
@@ -75,41 +75,29 @@ sub param {
     push @values, $params->[$i + 1] if $params->[$i] eq $name;
   }
 
-  return wantarray ? @values : $values[0];
+  wantarray ? @values : $values[0];
+}
+
+sub params {
+  my ($self, $params) = @_;
+  if ($params) { $self->{_params} = $params }
+  elsif (defined $self->{_string}) { $self->parse }
+  $self->{_params} ||= [];
 }
 
 sub parse {
-  my $self   = shift;
-  my $string = shift;
+  my ($self, $string) = @_;
+  $string = delete $self->{_string} unless defined $string;
 
   # Clear
   $self->params([]);
 
-  return $self unless defined $string;
-  my $charset = $self->charset;
-
-  # Detect query string without key/value pairs
-  if ($string !~ /\=/) {
-
-    # Replace "+" with whitespace
-    $string =~ s/\+/\ /g;
-
-    # Escaped string
-    if (index($string, '%') >= 0) {
-      url_unescape $string;
-      my $backup = $string;
-      decode $charset, $string if $charset;
-      $string = $backup unless defined $string;
-    }
-
-    $self->params([$string, undef]);
-    return $self;
-  }
-
   # Detect pair separator for reconstruction
+  return $self unless defined $string && length $string;
   $self->pair_separator(';') if $string =~ /\;/ && $string !~ /\&/;
 
   # W3C suggests to also accept ";" as a separator
+  my $charset = $self->charset;
   for my $pair (split /[\&\;]+/, $string) {
 
     # Parse
@@ -123,15 +111,13 @@ sub parse {
     $name  =~ s/\+/\ /g;
     $value =~ s/\+/\ /g;
 
-    # Escaped name
+    # Unescape
     if (index($name, '%') >= 0) {
       url_unescape $name;
       my $backup = $name;
       decode $charset, $name if $charset;
       $name = $backup unless defined $name;
     }
-
-    # Escaped value
     if (index($value, '%') >= 0) {
       url_unescape $value;
       my $backup = $value;
@@ -142,7 +128,7 @@ sub parse {
     push @{$self->params}, $name, $value;
   }
 
-  return $self;
+  $self;
 }
 
 # "Don't kid yourself, Jimmy. If a cow ever got the chance,
@@ -159,7 +145,7 @@ sub remove {
   }
   $self->params($params);
 
-  return $self;
+  $self;
 }
 
 sub to_hash {
@@ -183,23 +169,32 @@ sub to_hash {
     else { $params{$name} = $value }
   }
 
-  return \%params;
+  \%params;
 }
 
 sub to_string {
   my $self = shift;
 
+  # String
+  my $charset = $self->charset;
+  if (defined(my $string = $self->{_string})) {
+
+    # Escape
+    encode $charset, $string if $charset;
+    url_escape $string, "$Mojo::URL::UNRESERVED\\&\\;\\=\\+\\%";
+
+    return $string;
+  }
+
+  # Build pairs
   my $params = $self->params;
   return '' unless @{$self->params};
-
-  # Format
   my @params;
-  my $charset = $self->charset;
   for (my $i = 0; $i < @$params; $i += 2) {
     my $name  = $params->[$i];
     my $value = $params->[$i + 1];
 
-    # *( pchar / "/" / "?" ) with the exception of ";", "&" and "="
+    # Escape
     encode $charset, $name if $charset;
     url_escape $name, $Mojo::URL::UNRESERVED;
     if ($value) {
@@ -214,8 +209,9 @@ sub to_string {
     push @params, defined $value ? "$name=$value" : "$name";
   }
 
+  # Concatenate pairs
   my $separator = $self->pair_separator;
-  return join $separator, @params;
+  join $separator, @params;
 }
 
 1;
@@ -244,21 +240,14 @@ L<Mojo::Parameters> implements the following attributes.
   my $charset = $params->charset;
   $params     = $params->charset('UTF-8');
 
-Charset used for decoding parameters.
+Charset used for decoding parameters, defaults to C<UTF-8>.
 
 =head2 C<pair_separator>
 
   my $separator = $params->pair_separator;
   $params       = $params->pair_separator(';');
 
-Separator for parameter pairs.
-
-=head2 C<params>
-
-  my $parameters = $params->params;
-  $params        = $params->params(foo => 'b;ar', baz => 23);
-
-The parameters.
+Separator for parameter pairs, defaults to C<&>.
 
 =head1 METHODS
 
@@ -300,6 +289,13 @@ Merge parameters.
 
 Check parameter values.
 
+=head2 C<params>
+
+  my $parameters = $params->params;
+  $params        = $params->params([foo => 'b;ar', baz => 23]);
+
+Parsed parameters.
+
 =head2 C<parse>
 
   $params = $params->parse('foo=b%3Bar&baz=23');
@@ -14,7 +14,7 @@ has parts => sub { [] };
 sub new {
   my $self = shift->SUPER::new();
   $self->parse(@_);
-  return $self;
+  $self;
 }
 
 sub append {
@@ -28,7 +28,8 @@ sub append {
 
     push @{$self->parts}, $value;
   }
-  return $self;
+
+  $self;
 }
 
 sub canonicalize {
@@ -56,7 +57,7 @@ sub canonicalize {
   }
   $self->parts(\@path);
 
-  return $self;
+  $self;
 }
 
 # "Homer, the plant called.
@@ -70,13 +71,13 @@ sub clone {
   $clone->leading_slash($self->leading_slash);
   $clone->trailing_slash($self->trailing_slash);
 
-  return $clone;
+  $clone;
 }
 
 sub parse {
   my ($self, $path) = @_;
 
-  # Meta
+  # Leading and trailing slash
   $path = '' unless defined $path;
   $path =~ /^\// ? $self->leading_slash(1)  : $self->leading_slash(0);
   $path =~ /\/$/ ? $self->trailing_slash(1) : $self->trailing_slash(0);
@@ -96,13 +97,13 @@ sub parse {
   }
   $self->parts(\@parts);
 
-  return $self;
+  $self;
 }
 
 sub to_abs_string {
   my $self = shift;
   return $self->to_string if $self->leading_slash;
-  return '/' . $self->to_string;
+  '/' . $self->to_string;
 }
 
 sub to_string {
@@ -123,7 +124,7 @@ sub to_string {
   $path = "/$path" if $self->leading_slash;
   $path = "$path/" if @path && $self->trailing_slash;
 
-  return $path;
+  $path;
 }
 
 1;
@@ -138,6 +139,8 @@ Mojo::Path - Path
   use Mojo::Path;
 
   my $path = Mojo::Path->new('/foo/bar%3B/baz.html');
+  shift @{$path->parts};
+  print "$path";
 
 =head1 DESCRIPTION
 
@@ -11,10 +11,9 @@ has nph => 0;
 sub run {
   my $self = shift;
 
+  # Environment
   my $tx  = $self->on_transaction->($self);
   my $req = $tx->req;
-
-  # Environment
   $req->parse(\%ENV);
 
   # Store connection information
@@ -108,7 +107,7 @@ sub run {
   # Finish transaction
   $tx->on_finish->($tx);
 
-  return $res->code;
+  $res->code;
 }
 
 1;
@@ -23,6 +23,7 @@ has max_clients        => 1000;
 has max_requests       => 25;
 has websocket_timeout  => 300;
 
+# Regex for listen sockets
 my $SOCKET_RE = qr/^
   (http(?:s)?)\:\/\/   # Scheme
   (.+)                 # Host
@@ -38,9 +39,8 @@ my $SOCKET_RE = qr/^
 sub DESTROY {
   my $self = shift;
 
-  return unless my $loop = $self->ioloop;
-
   # Cleanup connections
+  return unless my $loop = $self->ioloop;
   my $cs = $self->{_cs} || {};
   for my $id (keys %$cs) { $loop->drop($id) }
 
@@ -86,10 +86,8 @@ sub setuidgid {
   if (my $group = $self->group) {
     if (my $gid = (getgrnam($group))[2]) {
 
-      # Cleanup
-      undef $!;
-
       # Switch
+      undef $!;
       $) = $gid;
       croak qq/Can't switch to effective group "$group": $!/ if $!;
     }
@@ -99,16 +97,14 @@ sub setuidgid {
   if (my $user = $self->user) {
     if (my $uid = (getpwnam($user))[2]) {
 
-      # Cleanup
-      undef $!;
-
       # Switch
+      undef $!;
       $> = $uid;
       croak qq/Can't switch to effective user "$user": $!/ if $!;
     }
   }
 
-  return $self;
+  $self;
 }
 
 sub _build_tx {
@@ -157,7 +153,7 @@ sub _build_tx {
   # Kept alive if we have more than one request on the connection
   $tx->kept_alive(1) if $c->{requests} > 1;
 
-  return $tx;
+  $tx;
 }
 
 sub _close {
@@ -168,7 +164,7 @@ sub _close {
 sub _drop {
   my ($self, $id) = @_;
 
-  # Finish
+  # Finish gracefully
   my $c = $self->{_cs}->{$id};
   if (my $tx = $c->{websocket} || $c->{transaction}) { $tx->server_close }
 
@@ -238,10 +234,9 @@ sub _listen {
   my ($self, $listen) = @_;
   return unless $listen;
 
+  # UNIX domain socket
   my $options = {};
   my $tls;
-
-  # UNIX domain socket
   if ($listen =~ /^file\:\/\/(.+)$/) { unlink $options->{file} = $1 }
 
   # Internet socket
@@ -294,9 +289,10 @@ sub _listen {
   }
 
   # Friendly message
+  return if $self->silent;
   $self->app->log->info("Server listening ($listen)");
   $listen =~ s/^(https?\:\/\/)\*/${1}127.0.0.1/i;
-  print "Server available at $listen.\n" unless $self->silent;
+  print "Server available at $listen.\n";
 }
 
 sub _read {
@@ -68,7 +68,7 @@ sub accept_connection {
   }
   $self->app->log->debug('Accepted FastCGI connection.') if DEBUG;
 
-  return $c;
+  $c;
 }
 
 sub read_record {
@@ -95,7 +95,7 @@ sub read_record {
       qq/Reading FastCGI record: $type - $id - "$body"./);
   }
 
-  return $self->type_name($type), $id, $body;
+  $self->type_name($type), $id, $body;
 }
 
 sub read_request {
@@ -178,19 +178,19 @@ sub read_request {
     }
   }
 
-  return $tx;
+  $tx;
 }
 
 sub role_name {
   my ($self, $role) = @_;
   return unless $role;
-  return $ROLES[$role - 1];
+  $ROLES[$role - 1];
 }
 
 sub role_number {
   my ($self, $role) = @_;
   return unless $role;
-  return $ROLE_NUMBERS{uc $role};
+  $ROLE_NUMBERS{uc $role};
 }
 
 sub run {
@@ -199,6 +199,7 @@ sub run {
   # Preload application
   $self->app;
 
+  # New incoming request
   while (my $c = $self->accept_connection) {
 
     # Request
@@ -225,28 +226,24 @@ sub run {
 sub type_name {
   my ($self, $type) = @_;
   return unless $type;
-  return $TYPES[$type - 1];
+  $TYPES[$type - 1];
 }
 
 sub type_number {
   my ($self, $type) = @_;
   return unless $type;
-  return $TYPE_NUMBERS{uc $type};
+  $TYPE_NUMBERS{uc $type};
 }
 
 sub write_records {
   my ($self, $c, $type, $id, $body) = @_;
-
-  # Required
   return unless defined $c && defined $type && defined $id;
-
-  # Defaults
   $body ||= '';
-  my $body_len = length $body;
 
   # Write records
-  my $empty = $body ? 0 : 1;
-  my $offset = 0;
+  my $empty    = $body ? 0 : 1;
+  my $offset   = 0;
+  my $body_len = length $body;
   while (($body_len > 0) || $empty) {
 
     # Need to split content
@@ -262,11 +259,11 @@ sub write_records {
         qq/Writing FastCGI record: $type - $id - "$chunk"./);
     }
 
+    # Write whole record
     my $record = pack $template, 1, $self->type_number($type), $id,
       $payload_len,
       $pad_len,
       substr($body, $offset, $payload_len);
-
     my $woffset = 0;
     while ($woffset < length $record) {
       my $written = $c->syswrite($record, undef, $woffset);
@@ -283,25 +280,23 @@ sub write_records {
 
       $woffset += $written;
     }
-
     $body_len -= $payload_len;
     $offset += $payload_len;
 
+    # Done
     last if $empty;
   }
 
-  return 1;
+  1;
 }
 
 sub write_response {
   my ($self, $tx) = @_;
   $self->app->log->debug('Writing FastCGI response.') if DEBUG;
 
-  my $c   = $tx->connection;
-  my $res = $tx->res;
-
   # Status
-  my $code    = $res->code    || 404;
+  my $res     = $tx->res;
+  my $code    = $res->code || 404;
   my $message = $res->message || $res->default_message;
   $res->headers->status("$code $message") unless $res->headers->status;
 
@@ -309,6 +304,7 @@ sub write_response {
   $res->fix_headers;
 
   # Headers
+  my $c      = $tx->connection;
   my $offset = 0;
   while (1) {
     my $chunk = $res->get_header_chunk($offset);
@@ -369,7 +365,7 @@ sub _nv_length {
     $len = unpack 'N', $len;
   }
 
-  return $len;
+  $len;
 }
 
 sub _read_chunk {
@@ -387,7 +383,7 @@ sub _read_chunk {
     $chunk .= $buffer;
   }
 
-  return $chunk;
+  $chunk;
 }
 
 1;
@@ -14,9 +14,7 @@ use POSIX qw/setsid WNOHANG/;
 use Scalar::Util 'weaken';
 
 # Preload
-use Mojo::DOM;
 use Mojo::UserAgent;
-use Mojolicious::Controller;
 
 use constant DEBUG => $ENV{HYPNOTOAD_DEBUG} || 0;
 
@@ -58,24 +56,18 @@ sub run {
   # Config
   $ENV{HYPNOTOAD_CONFIG} ||= abs_path $config;
 
-  # Production
+  # This is a production server
   $ENV{MOJO_MODE} ||= 'production';
 
   # Executable
   $ENV{HYPNOTOAD_EXE} ||= $0;
   $0 = $ENV{HYPNOTOAD_APP};
 
-  # Cleanup
-  delete $ENV{MOJO_COMMANDS_DONE};
-  delete $ENV{MOJO_RELOAD};
-
   # Clean start
   exec $ENV{HYPNOTOAD_EXE} unless $ENV{HYPNOTOAD_REV}++;
 
-  # Daemon
-  my $daemon = $self->{_daemon} = Mojo::Server::Daemon->new;
-
   # Preload application
+  my $daemon = $self->{_daemon} = Mojo::Server::Daemon->new;
   warn "APPLICATION $ENV{HYPNOTOAD_APP}\n" if DEBUG;
   $daemon->load_app($ENV{HYPNOTOAD_APP});
 
@@ -108,10 +100,8 @@ sub run {
     open STDERR, '>&STDOUT';
   }
 
-  # Config
-  my $c = $self->{_config};
-
   # Manager signals
+  my $c = $self->{_config};
   $SIG{INT} = $SIG{TERM} = sub { $self->{_done} = 1 };
   $SIG{CHLD} = sub {
     while ((my $pid = waitpid -1, WNOHANG) > 0) { $self->_reap($pid) }
@@ -134,11 +124,9 @@ sub run {
 sub _config {
   my $self = shift;
 
-  # File
+  # Load config file
   my $file = $ENV{HYPNOTOAD_CONFIG};
   warn "CONFIG $file\n" if DEBUG;
-
-  # Config
   my $c = {};
   if (-r $file) {
     unless ($c = do $file) {
@@ -150,84 +138,46 @@ sub _config {
   }
   $self->{_config} = $c;
 
-  # Graceful timeout
-  $c->{graceful_timeout} ||= 30;
-
-  # Heartbeat interval
+  # Hypnotoad settings
+  $c->{graceful_timeout}   ||= 30;
   $c->{heartbeat_interval} ||= 5;
-
-  # Heartbeat timeout
-  $c->{heartbeat_timeout} ||= 2;
-
-  # Lock file
+  $c->{heartbeat_timeout}  ||= 2;
   $c->{lock_file}
     ||= File::Spec->catfile($ENV{MOJO_TMPDIR} || File::Spec->tmpdir,
     "hypnotoad.$$.lock");
-
-  # PID file
   $c->{pid_file}
     ||= File::Spec->catfile(dirname($ENV{HYPNOTOAD_APP}), 'hypnotoad.pid');
-
-  # Reverse proxy support
-  $ENV{MOJO_REVERSE_PROXY} = 1 if $c->{proxy};
-
-  # Upgrade timeout
   $c->{upgrade_timeout} ||= 30;
+  $c->{workers}         ||= 4;
 
-  # Workers
-  $c->{workers} ||= 4;
-
-  # Daemon
+  # Daemon settings
+  $ENV{MOJO_REVERSE_PROXY} = 1 if $c->{proxy};
   my $daemon = $self->{_daemon};
-
-  # Backlog
   $daemon->backlog($c->{backlog}) if defined $c->{backlog};
-
-  # Clients
   $daemon->max_clients($c->{clients} || 1000);
-
-  # Group
   $daemon->group($c->{group}) if $c->{group};
-
-  # Keep alive requests
-  $daemon->max_requests($c->{keep_alive_requests} || 25);
-
-  # Keep alive timeout
+  $daemon->max_requests($c->{keep_alive_requests}      || 25);
   $daemon->keep_alive_timeout($c->{keep_alive_timeout} || 5);
-
-  # Listen
-  my $listen = $c->{listen} || ['http://*:8080'];
-  $listen = [$listen] unless ref $listen;
-  $daemon->listen($listen);
-
-  # User
   $daemon->user($c->{user}) if $c->{user};
-
-  # WebSocket timeout
   $daemon->websocket_timeout($c->{websocket_timeout} || 300);
-
-  # Accept limit
   $daemon->ioloop->max_accepts($c->{accepts} || 1000);
+  my $listen = $c->{listen} || ['http://*:8080'];
+  $listen = [$listen] unless ref $listen;
+  $daemon->listen($listen);
 }
 
 sub _heartbeat {
   my $self = shift;
 
-  # Poll
+  # Poll for heartbeats
   my $poll = $self->{_poll};
   $poll->poll(1);
-
-  # Readable
   return unless $poll->handles(POLLIN);
-
-  # Read
   return unless $self->{_reader}->sysread(my $chunk, 4194304);
 
-  # Parse
+  # Heartbeats
   while ($chunk =~ /(\d+)\n/g) {
     my $pid = $1;
-
-    # Heartbeat
     $self->{_workers}->{$pid}->{time} = time if $self->{_workers}->{$pid};
   }
 }
@@ -235,10 +185,8 @@ sub _heartbeat {
 sub _manage {
   my $self = shift;
 
-  # Config
-  my $c = $self->{_config};
-
   # Housekeeping
+  my $c = $self->{_config};
   if (!$self->{_done}) {
 
     # Spawn more workers
@@ -320,14 +268,12 @@ sub _manage {
 sub _pid {
   my $self = shift;
 
-  # PID file
+  # Check PID file
   my $file = $self->{_config}->{pid_file};
-
-  # Check
   return if -e $file;
   warn "PID $file\n" if DEBUG;
 
-  # Create
+  # Create one if it doesn't exist
   my $pid = IO::File->new($file, O_WRONLY | O_CREAT | O_EXCL, 0644)
     or croak qq/Can't create PID file "$file": $!/;
   print $pid $$;
@@ -365,30 +311,22 @@ sub _spawn {
 
   # Worker
   $ENV{HYPNOTOAD_WORKER} = 1;
-
-  # Daemon
   my $daemon = $self->{_daemon};
+  my $loop   = $daemon->ioloop;
+  my $c      = $self->{_config};
 
-  # Loop
-  my $loop = $daemon->ioloop;
-
-  # Config
-  my $c = $self->{_config};
-
-  # Lock file
+  # Prepare lock file
   my $file = $c->{lock_file};
   my $lock = IO::File->new("> $file")
     or croak qq/Can't open lock file "$file": $!/;
 
-  weaken $self;
-
   # Accept mutex
   $loop->on_lock(
     sub {
 
       # Blocking
       my $l;
-      if (my $blocking = $_[1]) {
+      if ($_[1]) {
         eval {
           local $SIG{ALRM} = sub { die "alarm\n" };
           my $old = alarm 1;
@@ -404,12 +342,13 @@ sub _spawn {
       # Non blocking
       else { $l = flock $lock, LOCK_EX | LOCK_NB }
 
-      return $l;
+      $l;
     }
   );
   $loop->on_unlock(sub { flock $lock, LOCK_UN });
 
   # Heartbeat
+  weaken $self;
   my $cb;
   $cb = sub {
     my $loop = shift;
@@ -451,7 +390,7 @@ Mojo::Server::Hypnotoad - ALL GLORY TO THE HYPNOTOAD!
   use Mojo::Server::Hypnotoad;
 
   my $toad = Mojo::Server::Hypnotoad->new;
-  $toad->run('myapp.pl', 'hypnotoad.conf');
+  $toad->run('./myapp.pl', './hypnotoad.conf');
 
 =head1 DESCRIPTION
 
@@ -460,6 +399,10 @@ io HTTP 1.1 and WebSocket server built around the very well tested and
 reliable L<Mojo::Server::Daemon> with C<IPv6>, C<TLS>, C<Bonjour>, C<epoll>,
 C<kqueue> and hot deployment support that just works.
 
+To start applications with it you can use the L<hypnotoad> script.
+
+  % hypnotoad myapp.pl
+
 Optional modules L<IO::KQueue>, L<IO::Epoll>, L<IO::Socket::IP>,
 L<IO::Socket::SSL> and L<Net::Rendezvous::Publish> are supported
 transparently and used if installed.
@@ -664,7 +607,7 @@ Start server.
 You can set the C<HYPNOTOAD_DEBUG> environment variable to get some advanced
 diagnostics information printed to C<STDERR>.
 
-  MOJO_HYPNOTOAD_DEBUG=1
+  HYPNOTOAD_DEBUG=1
 
 =head1 SEE ALSO
 
@@ -0,0 +1,193 @@
+package Mojo::Server::Morbo;
+use Mojo::Base -base;
+
+use Carp 'croak';
+use Mojo::Home;
+use Mojo::Server::Daemon;
+use POSIX 'WNOHANG';
+
+use constant DEBUG => $ENV{MORBO_DEBUG} || 0;
+
+has listen => sub { [] };
+has watch  => sub { [qw/lib templates/] };
+
+# Cache stats
+my $STATS = {};
+
+# "All in all, this is one day Mittens the kitten won’t soon forget.
+#  Kittens give Morbo gas.
+#  In lighter news, the city of New New York is doomed.
+#  Blame rests with known human Professor Hubert Farnsworth and his tiny,
+#  inferior brain."
+sub run {
+  my ($self, $app) = @_;
+  warn "MANAGER STARTED $$\n" if DEBUG;
+
+  # Watch files and manage worker
+  $SIG{CHLD} = sub { $self->_reap };
+  $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = sub {
+    $self->{_done} = 1;
+    kill 'TERM', $self->{_running} if $self->{_running};
+  };
+  unshift @{$self->watch}, $app;
+  $self->{_modified} = 1;
+  $self->_manage while !$self->{_done} || $self->{_running};
+  exit 0;
+}
+
+# "And so with two weeks left in the campaign, the question on everyone’s
+#  mind is, who will be the president of Earth?
+#  Jack Johnson or bitter rival John Jackson.
+#  Two terrific candidates, Morbo?
+#  All humans are vermin in the eyes of Morbo!"
+sub _manage {
+  my $self = shift;
+
+  # Discover files
+  warn "DISCOVERING NEW FILES\n" if DEBUG;
+  my @files;
+  for my $watch (@{$self->watch}) {
+    if (-d $watch) {
+      my $home = Mojo::Home->new->parse($watch);
+      push @files, $home->rel_file($_) for @{$home->list_files};
+    }
+    elsif (-r $watch) { push @files, $watch }
+  }
+
+  # Check files
+  for my $file (@files) {
+    warn "CHECKING $file\n" if DEBUG;
+    next unless defined(my $mtime = (stat $file)[9]);
+
+    # Startup time as default
+    $STATS->{$file} = $^T unless defined $STATS->{$file};
+
+    # Modified
+    if ($mtime > $STATS->{$file}) {
+      warn "MODIFIED $file\n" if DEBUG;
+      kill 'TERM', $self->{_running} if $self->{_running};
+      $self->{_modified} = 1;
+      $STATS->{$file} = $mtime;
+    }
+  }
+
+  # Housekeeping
+  $self->_reap;
+  delete $self->{_running} if $self->{_running} && !kill 0, $self->{_running};
+  $self->_spawn if !$self->{_running} && delete $self->{_modified};
+  sleep 1;
+}
+
+sub _reap {
+  my $self = shift;
+  while ((my $pid = waitpid -1, WNOHANG) > 0) {
+    warn "WORKER STOPPED $pid\n" if DEBUG;
+    delete $self->{_running};
+  }
+}
+
+# "Morbo cannot read his teleprompter.
+#  He forgot how you say that letter that looks like a man wearing a hat.
+#  It's a T. It goes 'tuh'.
+#  Hello, little man. I will destroy you!"
+sub _spawn {
+  my $self = shift;
+
+  # Fork
+  my $manager = $$;
+  $ENV{MORBO_REV}++;
+  croak "Can't fork: $!" unless defined(my $pid = fork);
+
+  # Manager
+  return $self->{_running} = $pid if $pid;
+
+  # Worker
+  warn "WORKER STARTED $$\n" if DEBUG;
+  $SIG{CHLD} = 'DEFAULT';
+  $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = sub { $self->{_done} = 1 };
+  my $daemon = Mojo::Server::Daemon->new;
+  $daemon->load_app($self->watch->[0]);
+  $daemon->silent(1) if $ENV{MORBO_REV} > 1;
+  $daemon->listen($self->listen) if @{$self->listen};
+  $daemon->prepare_ioloop;
+  my $loop = $daemon->ioloop;
+  $loop->recurring(
+    1 => sub { shift->stop if !kill(0, $manager) || $self->{_done} });
+  $loop->start;
+  exit 0;
+}
+
+1;
+__END__
+
+=head1 NAME
+
+Mojo::Server::Morbo - DOOOOOOOOOOOOOOOOOOM!
+
+=head1 SYNOPSIS
+
+  use Mojo::Server::Morbo;
+
+  my $morbo = Mojo::Server::Morbo->new;
+  $morbo->run('./myapp.pl');
+
+=head1 DESCRIPTION
+
+L<Mojo::Server::Morbo> is a full featured self-restart capable async io HTTP
+1.1 and WebSocket server built around the very well tested and reliable
+L<Mojo::Server::Daemon> with C<IPv6>, C<TLS>, C<Bonjour>, C<epoll> and
+C<kqueue> support.
+
+To start applications with it you can use the L<morbo> script.
+
+  % morbo myapp.pl
+
+Optional modules L<IO::KQueue>, L<IO::Epoll>, L<IO::Socket::IP>,
+L<IO::Socket::SSL> and L<Net::Rendezvous::Publish> are supported
+transparently and used if installed.
+
+Note that this module is EXPERIMENTAL and might change without warning!
+
+=head1 ATTRIBUTES
+
+L<Mojo::Server::Morbo> implements the following attributes.
+
+=head2 C<listen>
+
+  my $listen = $morbo->listen;
+  $morbo     = $morbo->listen(['http://*:3000']);
+
+List of ports and files to listen on, defaults to C<http://*:3000>.
+
+=head2 C<watch>
+
+  my $watch = $morbo->watch;
+  $morbo    = $morbo->watch(['/home/sri/myapp']);
+
+Files and directories to watch for changes, defaults to the application
+script as well as the C<lib> and C<templates> directories in the current
+working directory.
+
+=head1 METHODS
+
+L<Mojo::Server::Morbo> inherits all methods from L<Mojo::Base> and implements
+the following new ones.
+
+=head2 C<run>
+
+  $morbo->run('script/myapp');
+
+Start server.
+
+=head1 DEBUGGING
+
+You can set the C<MORBO_DEBUG> environment variable to get some advanced
+diagnostics information printed to C<STDERR>.
+
+  MORBO_DEBUG=1
+
+=head1 SEE ALSO
+
+L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicio.us>.
+
+=cut
@@ -10,10 +10,9 @@ use constant CHUNK_SIZE => $ENV{MOJO_CHUNK_SIZE} || 131072;
 sub run {
   my ($self, $env) = @_;
 
+  # Environment
   my $tx  = $self->on_transaction->($self);
   my $req = $tx->req;
-
-  # Environment
   $req->parse($env);
 
   # Store connection information
@@ -34,10 +33,8 @@ sub run {
   # Handle
   $self->on_request->($self, $tx);
 
-  my $res = $tx->res;
-  my $code = $res->code || 404;
-
   # Fix headers
+  my $res = $tx->res;
   $res->fix_headers;
 
   # Response headers
@@ -55,7 +52,9 @@ sub run {
   # Finish transaction
   $tx->on_finish->($tx);
 
-  return [$code, \@headers, $body];
+  # PSGI response
+  my $code = $res->code || 404;
+  [$code, \@headers, $body];
 }
 
 package Mojo::Server::PSGI::_Handle;
@@ -87,7 +86,7 @@ sub getline {
     return $chunk;
   }
 
-  return;
+  undef;
 }
 
 1;
@@ -3,6 +3,7 @@ use Mojo::Base -base;
 
 use Carp 'croak';
 use Mojo::Loader;
+use Mojo::Util 'md5_sum';
 use Scalar::Util 'blessed';
 
 has app => sub {
@@ -30,13 +31,6 @@ has on_request => sub {
 has on_transaction => sub {
   sub {
     my $self = shift;
-
-    # Reload
-    if ($self->reload) {
-      if (my $e = Mojo::Loader->reload) { warn $e }
-      delete $self->{app};
-    }
-
     $self->app->on_transaction->($self->app);
   };
 };
@@ -46,21 +40,33 @@ has on_websocket => sub {
     $self->app->on_websocket->($self->app, @_)->server_handshake;
   };
 };
-has reload => sub { $ENV{MOJO_RELOAD} || 0 };
 
 sub load_app {
   my ($self, $file) = @_;
-  my $app;
+
+  # Cleanup environment
   local $ENV{MOJO_APP_LOADER} = 1;
-  unless ($app = do $file) {
-    die qq/Can't load application "$file": $@/ if $@;
-    die qq/Can't load application "$file": $!/ unless defined $app;
-    die qq/Can't load application' "$file".\n/ unless $app;
+  local $ENV{MOJO_APP};
+  local $ENV{MOJO_EXE};
+
+  # Try to load application from script into sandbox
+  my $class = 'Mojo::Server::SandBox::' . md5_sum($file . $$);
+  my $app;
+  die $@ unless eval <<EOF;
+package $class;
+{
+  unless (\$app = do \$file) {
+    die qq/Can't load application "\$file": \$@/ if \$@;
+    die qq/Can't load application "\$file": \$!/ unless defined \$app;
+    die qq/Can't load application' "\$file".\n/ unless \$app;
   }
+}
+1;
+EOF
   die qq/"$file" is not a valid application.\n/
     unless blessed $app && $app->isa('Mojo');
   $self->app($app);
-  return $app;
+  $app;
 }
 
 # "Are you saying you're never going to eat any animal again? What about
@@ -124,7 +130,7 @@ L<Mojo::HelloWorld>.
     my ($self, $tx) = @_;
   });
 
-Request callback.
+Callback to be invoked for requests that need a response.
 
 =head2 C<on_transaction>
 
@@ -134,7 +140,7 @@ Request callback.
     return Mojo::Transaction::HTTP->new;
   });
 
-Transaction builder callback.
+Callback to be invoked when a new transaction is needed.
 
 =head2 C<on_websocket>
 
@@ -143,14 +149,7 @@ Transaction builder callback.
     my ($self, $tx) = @_;
   });
 
-WebSocket handshake callback.
-
-=head2 C<reload>
-
-  my $reload = $server->reload;
-  $server    = $server->reload(1);
-
-Activate automatic reloading.
+Callback to be invoked for WebSocket handshakes.
 
 =head1 METHODS
 
@@ -20,7 +20,7 @@ has escape_mark     => '=';
 has expression_mark => '=';
 has line_start      => '%';
 has name            => 'template';
-has namespace       => 'Mojo::Template::Context';
+has namespace       => 'Mojo::Template::SandBox';
 has tag_start       => '<%';
 has tag_end         => '%>';
 has template        => '';
@@ -43,7 +43,7 @@ sub escape;
     $v = "$_[0]";
   }
   Mojo::Util::xml_escape $v;
-  return $v;
+  $v;
 };
 use strict; use warnings;
 EOF
@@ -72,7 +72,7 @@ sub build {
       if ($type eq 'cpen') {
 
         # End block
-        $lines[-1] .= 'return $_M }';
+        $lines[-1] .= 'return b($_M) }';
 
         # No following code
         my $next = $line->[$j + 3];
@@ -146,15 +146,14 @@ sub build {
   $self->code(join "\n", @lines);
   $self->tree([]);
 
-  return $self;
+  $self;
 }
 
 sub compile {
   my $self = shift;
 
-  return unless my $code = $self->code;
-
   # Compile
+  return unless my $code = $self->code;
   my $compiled = eval $code;
 
   # Use local stacktrace for compile exceptions
@@ -163,7 +162,7 @@ sub compile {
     if $@;
 
   $self->compiled($compiled);
-  return;
+  undef;
 }
 
 sub interpret {
@@ -172,8 +171,6 @@ sub interpret {
   # Compile
   unless ($self->compiled) {
     my $e = $self->compile;
-
-    # Exception
     return $e if ref $e;
   }
   my $compiled = $self->compiled;
@@ -192,7 +189,7 @@ sub interpret {
     Mojo::Exception->new($@, [$self->template], $self->name)->verbose(1)
     if $@;
 
-  return $output;
+  $output;
 }
 
 # "I am so smart! I am so smart! S-M-R-T! I mean S-M-A-R-T..."
@@ -291,8 +288,6 @@ sub parse {
 
     # Perl line
     if ($line =~ /$line_re/) {
-
-      # Token
       my @token = ();
 
       # Capture end
@@ -422,7 +417,7 @@ sub parse {
     push @{$self->tree}, \@token;
   }
 
-  return $self;
+  $self;
 }
 
 sub render {
@@ -440,7 +435,7 @@ sub render {
   return $e if $e;
 
   # Interpret
-  return $self->interpret(@_);
+  $self->interpret(@_);
 }
 
 sub render_file {
@@ -462,7 +457,7 @@ sub render_file {
   $tmpl = decode($self->encoding, $tmpl) if $self->encoding;
 
   # Render
-  return $self->render($tmpl, @_);
+  $self->render($tmpl, @_);
 }
 
 sub render_file_to_file {
@@ -472,12 +467,10 @@ sub render_file_to_file {
 
   # Render
   my $output = $self->render_file($spath, @_);
-
-  # Exception
   return $output if ref $output;
 
   # Write to file
-  return $self->_write_file($tpath, $output);
+  $self->_write_file($tpath, $output);
 }
 
 sub render_to_file {
@@ -487,12 +480,10 @@ sub render_to_file {
 
   # Render
   my $output = $self->render($tmpl, @_);
-
-  # Exception
   return $output if ref $output;
 
   # Write to file
-  return $self->_write_file($path, $output);
+  $self->_write_file($path, $output);
 }
 
 sub _trim_line {
@@ -523,7 +514,7 @@ sub _trim_line {
     return 1 if length $value;
   }
 
-  return;
+  undef;
 }
 
 sub _write_file {
@@ -539,7 +530,7 @@ sub _write_file {
   # Write to file
   $file->syswrite($output) or croak "Can't write to file '$path': $!";
 
-  return;
+  undef;
 }
 
 1;
@@ -794,7 +785,7 @@ Note that this method is attribute and might change without warning!
   my $namespace = $mt->namespace;
   $mt           = $mt->namespace('main');
 
-Namespace used to compile templates, defaults to C<Mojo::Template::Context>.
+Namespace used to compile templates, defaults to C<Mojo::Template::SandBox>.
 
 =head2 C<prepend>
 
@@ -13,17 +13,16 @@ has res => sub { Mojo::Message::Response->new };
 sub client_read {
   my ($self, $chunk) = @_;
 
-  my $req  = $self->req;
-  my $res  = $self->res;
-  my $read = length $chunk;
-
   # Preserve state
   my $preserved = $self->{_state};
 
   # Done
+  my $read = length $chunk;
   $self->{_state} = 'done' if $read == 0;
 
   # HEAD response
+  my $req = $self->req;
+  my $res = $self->res;
   if ($req->method =~ /^head$/i) {
     $res->parse_until_body($chunk);
     $self->{_state} = 'done' if $res->content->is_parsing_body;
@@ -46,20 +45,18 @@ sub client_read {
   # Check for errors
   $self->{_state} = 'done' if $self->error;
 
-  return $self;
+  $self;
 }
 
 sub client_write {
   my $self = shift;
 
-  my $chunk = '';
-  my $req   = $self->req;
-
   # Offsets
   $self->{_offset} ||= 0;
   $self->{_write}  ||= 0;
 
   # Writing
+  my $req = $self->req;
   unless ($self->{_state}) {
 
     # Connection header
@@ -77,6 +74,7 @@ sub client_write {
   }
 
   # Start line
+  my $chunk = '';
   if ($self->{_state} eq 'write_start_line') {
     my $buffer = $req->get_start_line_chunk($self->{_offset});
 
@@ -84,7 +82,6 @@ sub client_write {
     my $written = defined $buffer ? length $buffer : 0;
     $self->{_write}  = $self->{_write} - $written;
     $self->{_offset} = $self->{_offset} + $written;
-
     $chunk .= $buffer;
 
     # Done
@@ -103,7 +100,6 @@ sub client_write {
     my $written = defined $buffer ? length $buffer : 0;
     $self->{_write}  = $self->{_write} - $written;
     $self->{_offset} = $self->{_offset} + $written;
-
     $chunk .= $buffer;
 
     # Done
@@ -126,7 +122,6 @@ sub client_write {
     my $written = defined $buffer ? length $buffer : 0;
     $self->{_write}  = $self->{_write} - $written;
     $self->{_offset} = $self->{_offset} + $written;
-
     $chunk .= $buffer if defined $buffer;
 
     # End
@@ -140,7 +135,7 @@ sub client_write {
     $self->{_state} = 'read_response' if $self->{_write} <= 0;
   }
 
-  return $chunk;
+  $chunk;
 }
 
 sub keep_alive {
@@ -152,12 +147,11 @@ sub keep_alive {
     return $self;
   }
 
-  my $req = $self->req;
-  my $res = $self->res;
-
   # No keep alive for 0.9 and 1.0
+  my $req     = $self->req;
   my $version = $req->version;
   $self->{keep_alive} ||= 0 if $req->version eq '0.9' || $version eq '1.0';
+  my $res = $self->res;
   $version = $res->version;
   $self->{keep_alive} ||= 0 if $version eq '0.9' || $version eq '1.0';
 
@@ -177,7 +171,7 @@ sub keep_alive {
   # Default
   $self->{keep_alive} = 1 unless defined $self->{keep_alive};
 
-  return $self->{keep_alive};
+  $self->{keep_alive};
 }
 
 sub server_leftovers {
@@ -191,20 +185,19 @@ sub server_leftovers {
   # Done
   $req->{_state} = 'done';
 
-  return $leftovers;
+  $leftovers;
 }
 
 sub server_read {
   my ($self, $chunk) = @_;
 
-  my $req = $self->req;
-  my $res = $self->res;
-
   # Parse
+  my $req = $self->req;
   $req->parse($chunk) unless $req->error;
   $self->{_state} ||= 'read';
 
   # Parser error
+  my $res     = $self->res;
   my $handled = $self->{_handled};
   if ($req->error && !$handled) {
 
@@ -245,7 +238,7 @@ sub server_read {
     }
   }
 
-  return $self;
+  $self;
 }
 
 sub server_write {
@@ -259,10 +252,8 @@ sub server_write {
   $self->{_offset} ||= 0;
   $self->{_write}  ||= 0;
 
-  my $req = $self->req;
-  my $res = $self->res;
-
   # Writing
+  my $res = $self->res;
   if ($self->{_state} eq 'write') {
 
     # Connection header
@@ -285,7 +276,6 @@ sub server_write {
     my $written = defined $buffer ? length $buffer : 0;
     $self->{_write}  = $self->{_write} - $written;
     $self->{_offset} = $self->{_offset} + $written;
-
     $chunk .= $buffer;
 
     # Done
@@ -304,14 +294,13 @@ sub server_write {
     my $written = defined $buffer ? length $buffer : 0;
     $self->{_write}  = $self->{_write} - $written;
     $self->{_offset} = $self->{_offset} + $written;
-
     $chunk .= $buffer;
 
     # Done
     if ($self->{_write} <= 0) {
 
       # HEAD request
-      if ($req->method =~ /^head$/i) {
+      if ($self->req->method =~ /^head$/i) {
 
         # Don't send body if request method is HEAD
         $self->{_state} = 'done';
@@ -356,7 +345,6 @@ sub server_write {
       my $written = defined $buffer ? length $buffer : 0;
       $self->{_write}  = $self->{_write} - $written;
       $self->{_offset} = $self->{_offset} + $written;
-
       if (defined $buffer) {
         $chunk .= $buffer;
         delete $self->{_delay};
@@ -378,7 +366,7 @@ sub server_write {
     }
   }
 
-  return $chunk;
+  $chunk;
 }
 
 1;
@@ -409,26 +397,19 @@ described in RFC 2616.
 L<Mojo::Transaction::HTTP> inherits all attributes from L<Mojo::Transaction>
 and implements the following new ones.
 
-=head2 C<keep_alive>
-
-  my $keep_alive = $tx->keep_alive;
-  $tx            = $tx->keep_alive(1);
-
-Connection can be kept alive.
-
 =head2 C<on_upgrade>
 
   my $cb = $tx->on_upgrade;
   $tx    = $tx->on_upgrade(sub {...});
 
-WebSocket upgrade callback.
+Callback to be invoked for WebSocket upgrades.
 
 =head2 C<on_request>
 
   my $cb = $tx->on_request;
   $tx    = $tx->on_request(sub {...});
 
-Request callback.
+Callback to be invoked for requests.
 
 =head2 C<req>
 
@@ -461,6 +442,13 @@ Read and process client data.
 
 Write client data.
 
+=head2 C<keep_alive>
+
+  my $keep_alive = $tx->keep_alive;
+  $tx            = $tx->keep_alive(1);
+
+Connection can be kept alive.
+
 =head2 C<server_leftovers>
 
   my $leftovers = $tx->server_leftovers;
@@ -34,7 +34,7 @@ sub client_challenge {
   # WebSocket challenge
   my $solution = $self->_challenge($self->req->headers->sec_websocket_key);
   return unless $solution eq $self->res->headers->sec_websocket_accept;
-  return 1;
+  1;
 }
 
 sub client_close { shift->server_close(@_) }
@@ -55,7 +55,7 @@ sub client_handshake {
   b64_encode $key, '';
   $headers->sec_websocket_key($key) unless $headers->sec_websocket_key;
 
-  return $self;
+  $self;
 }
 
 sub client_read  { shift->server_read(@_) }
@@ -71,7 +71,7 @@ sub finish {
   # Finish after writing
   $self->{_finished} = 1;
 
-  return $self;
+  $self;
 }
 
 sub is_websocket {1}
@@ -86,41 +86,34 @@ sub res            { shift->handshake->res(@_) }
 sub resume {
   my $self = shift;
   $self->handshake->resume;
-  return $self;
+  $self;
 }
 
 sub send_message {
   my ($self, $message, $cb) = @_;
-
-  # Drain callback
   $self->{_drain} = $cb if $cb;
-
-  # Encode
   $message = '' unless defined $message;
   encode 'UTF-8', $message;
-
   $self->_send_frame(TEXT, $message);
 }
 
 sub server_handshake {
   my $self = shift;
 
-  my $req         = $self->req;
+  # Handshake
   my $res         = $self->res;
-  my $req_headers = $req->headers;
   my $res_headers = $res->headers;
-
-  # Handshake
   $res->code(101);
   $res_headers->upgrade('websocket');
   $res_headers->connection('Upgrade');
+  my $req_headers = $self->req->headers;
   my $protocol = $req_headers->sec_websocket_protocol || '';
   $protocol =~ /^\s*([^\,]+)/;
   $res_headers->sec_websocket_protocol($1) if $1;
   $res_headers->sec_websocket_accept(
     $self->_challenge($req_headers->sec_websocket_key));
 
-  return $self;
+  $self;
 }
 
 # "Being eaten by crocodile is just like going to sleep...
@@ -137,8 +130,6 @@ sub server_read {
 
   # Full frames
   while (my $frame = $self->_parse_frame) {
-
-    # Op
     my $op = $frame->[1] || CONTINUATION;
 
     # Ping
@@ -174,7 +165,7 @@ sub server_read {
   # Resume
   $self->on_resume->($self);
 
-  return $self;
+  $self;
 }
 
 sub server_write {
@@ -193,12 +184,11 @@ sub server_write {
   # Empty buffer
   my $write = $self->{_write};
   $self->{_write} = '';
-  return $write;
+  $write;
 }
 
 sub _build_frame {
   my ($self, $op, $payload) = @_;
-
   warn "BUILDING FRAME\n" if DEBUG;
 
   # Head
@@ -249,7 +239,7 @@ sub _build_frame {
   # Payload
   $frame .= $payload;
 
-  return $frame;
+  $frame;
 }
 
 sub _challenge {
@@ -264,12 +254,11 @@ sub _challenge {
   # Accept
   b64_encode $challenge, '';
 
-  return $challenge;
+  $challenge;
 }
 
 sub _parse_frame {
   my $self = shift;
-
   warn "PARSING FRAME\n" if DEBUG;
 
   # Head
@@ -333,11 +322,10 @@ sub _parse_frame {
     warn "UNMASKING PAYLOAD\n" if DEBUG;
     $payload = _xor_mask($payload, substr($payload, 0, 4, ''));
   }
-
   warn "PAYLOAD: $payload\n" if DEBUG;
   $self->{_read} = $buffer;
 
-  return [$fin, $op, $payload];
+  [$fin, $op, $payload];
 }
 
 sub _send_frame {
@@ -365,7 +353,7 @@ sub _xor_mask {
   $output .= $_ ^ $mask while length($_ = substr($input, 0, 512, '')) == 512;
   $output .= $_ ^ substr($mask, 0, length, '');
 
-  return $output;
+  $output;
 }
 
 1;
@@ -395,7 +383,8 @@ L<Mojo::Transaction> and implements the following new ones.
   my $handshake = $ws->handshake;
   $ws           = $ws->handshake(Mojo::Transaction::HTTP->new);
 
-The original handshake transaction.
+The original handshake transaction, defaults to a L<Mojo::Transaction::HTTP>
+object.
 
 =head2 C<masked>
 
@@ -416,7 +405,7 @@ Maximum WebSocket message size in bytes, defaults to C<262144>.
   my $cb = $ws->on_message;
   $ws    = $ws->on_message(sub {...});
 
-The callback that receives decoded messages one by one.
+Callback to be invoked for each decoded message.
 
   $ws->on_message(sub {
     my ($self, $message) = @_;
@@ -19,12 +19,12 @@ sub error {
   return $req->error if $req->error;
   my $res = $self->res;
   return $res->error if $res->error;
-  return;
+  undef;
 }
 
 sub is_done {
   return 1 if (shift->{_state} || '') eq 'done';
-  return;
+  undef;
 }
 
 sub is_websocket {0}
@@ -36,7 +36,7 @@ sub is_writing {
       || $state eq 'write_start_line'
       || $state eq 'write_headers'
       || $state eq 'write_body';
-  return;
+  undef;
 }
 
 sub remote_address {
@@ -67,7 +67,7 @@ sub remote_address {
   }
 
   # Get
-  return $self->{remote_address};
+  $self->{remote_address};
 }
 
 sub req { croak 'Method "req" not implemented by subclass' }
@@ -87,16 +87,13 @@ sub resume {
   # Callback
   $self->on_resume->($self);
 
-  return $self;
+  $self;
 }
 
 sub server_close {
   my $self = shift;
-
-  # Transaction finished
   $self->on_finish->($self);
-
-  return $self;
+  $self;
 }
 
 sub server_read  { croak 'Method "server_read" not implemented by subclass' }
@@ -105,7 +102,7 @@ sub server_write { croak 'Method "server_write" not implemented by subclass' }
 sub success {
   my $self = shift;
   return $self->res unless $self->error;
-  return;
+  undef;
 }
 
 1;
@@ -167,7 +164,7 @@ Local interface port.
   my $cb = $tx->on_finish;
   $tx    = $tx->on_finish(sub {...});
 
-Callback signaling that the transaction has been finished.
+Callback to be invoked when the transaction has been finished.
 
   $tx->on_finish(sub {
     my $self = shift;
@@ -40,7 +40,7 @@ our $IPV6_RE = qr/(?:
 sub new {
   my $self = shift->SUPER::new();
   $self->parse(@_);
-  return $self;
+  $self;
 }
 
 sub authority {
@@ -87,7 +87,7 @@ sub authority {
   $authority .= lc($host || '');
   $authority .= ":$port" if $port;
 
-  return $authority;
+  $authority;
 }
 
 sub clone {
@@ -101,7 +101,7 @@ sub clone {
   $clone->fragment($self->fragment);
   $clone->base($self->base->clone) if $self->{base};
 
-  return $clone;
+  $clone;
 }
 
 sub ihost {
@@ -138,23 +138,23 @@ sub ihost {
     push @encoded, $part;
   }
 
-  return join '.', @encoded;
+  join '.', @encoded;
 }
 
 sub is_abs {
   my $self = shift;
   return 1 if $self->scheme && $self->authority;
-  return;
+  undef;
 }
 
 sub is_ipv4 {
   return 1 if shift->host =~ $IPV4_RE;
-  return;
+  undef;
 }
 
 sub is_ipv6 {
   return 1 if shift->host =~ $IPV6_RE;
-  return;
+  undef;
 }
 
 sub parse {
@@ -164,14 +164,13 @@ sub parse {
   # Official regex
   my ($scheme, $authority, $path, $query, $fragment) = $url
     =~ m|(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?|;
-
   $self->scheme($scheme);
   $self->authority($authority);
   $self->path->parse($path);
-  $self->query->parse($query);
+  $self->query($query);
   $self->fragment($fragment);
 
-  return $self;
+  $self;
 }
 
 sub path {
@@ -203,7 +202,7 @@ sub path {
 
   # Get
   $self->{path} ||= Mojo::Path->new;
-  return $self->{path};
+  $self->{path};
 }
 
 sub query {
@@ -232,18 +231,15 @@ sub query {
       $q->append(%{$_[0]});
     }
 
-    # Replace with string or object
-    else {
-      $self->{query} =
-        !ref $_[0] ? Mojo::Parameters->new->append($_[0]) : $_[0];
-    }
+    # Replace with string
+    else { $self->{query} = Mojo::Parameters->new($_[0]) }
 
     return $self;
   }
 
   # Get
   $self->{query} ||= Mojo::Parameters->new;
-  return $self->{query};
+  $self->{query};
 }
 
 sub to_abs {
@@ -280,7 +276,7 @@ sub to_abs {
   $new->trailing_slash($old->trailing_slash);
   $abs->path($new);
 
-  return $abs;
+  $abs;
 }
 
 sub to_rel {
@@ -300,18 +296,16 @@ sub to_rel {
   $rel->scheme('');
   $rel->authority('');
 
+  # Characters after the right-most '/' need to go
   $rel->base($base->clone);
   my $splice = @{$base->path->parts};
-
-  # Characters after the right-most '/' need to go
   $splice -= 1 unless $base->path->trailing_slash;
-
   my $path = $rel->path->clone;
   splice @{$path->parts}, 0, $splice if $splice;
   $rel->path($path);
   $rel->path->leading_slash(0);
 
-  return $rel;
+  $rel;
 }
 
 # "Dad, what's a Muppet?
@@ -320,26 +314,25 @@ sub to_rel {
 sub to_string {
   my $self = shift;
 
+  # Scheme and authority
+  my $url       = '';
   my $scheme    = $self->scheme;
   my $authority = $self->authority;
-  my $path      = $self->path;
-  my $query     = $self->query;
-  my $url       = '';
-
-  # Scheme and authority
   if ($scheme && $authority) {
     $url .= lc "$scheme://";
     $url .= "$authority";
   }
 
   # Path
+  my $path  = $self->path;
   my $slash = $path->leading_slash;
   $path->leading_slash(0) if !$scheme && @{$self->base->path->parts};
   $url .= $path;
   $path->leading_slash($slash);
 
   # Query
-  $url .= "?$query" if @{$query->params};
+  my $query = join '', $self->query;
+  $url .= "?$query" if length $query;
 
   # Fragment
   if (my $fragment = $self->fragment) {
@@ -349,7 +342,7 @@ sub to_string {
     $url .= "#$fragment";
   }
 
-  return $url;
+  $url;
 }
 
 1;
@@ -14,10 +14,8 @@ has [qw/filename name/];
 #  This game makes no sense.
 #  Tell that to the good men who just lost their lives... SEMPER-FI!"
 sub move_to { shift->asset->move_to(@_) }
-
-sub size { shift->asset->size }
-
-sub slurp { shift->asset->slurp }
+sub size    { shift->asset->size }
+sub slurp   { shift->asset->slurp }
 
 1;
 __END__
@@ -47,8 +45,8 @@ L<Mojo::Upload> implements the following attributes.
   my $asset = $upload->asset;
   $upload   = $upload->asset(Mojo::Asset::File->new);
 
-Asset containing the uploaded data, usually a L<Mojo::Asset::Memory> or
-L<Mojo::Asset::File> object.
+Asset containing the uploaded data, defaults to a L<Mojo::Asset::File>
+object.
 
 =head2 C<filename>
 
@@ -62,7 +60,7 @@ Name of the uploaded file.
   my $headers = $upload->headers;
   $upload     = $upload->headers(Mojo::Headers->new);
 
-Headers for upload, usually a L<Mojo::Headers> object.
+Headers for upload, defaults to a L<Mojo::Headers> object.
 
 =head2 C<name>
 
@@ -160,7 +160,7 @@ sub build_form_tx {
   }
 
   return $tx unless wantarray;
-  return $tx, $cb;
+  $tx, $cb;
 }
 
 # "Homer, it's easy to criticize.
@@ -187,7 +187,7 @@ sub build_tx {
   $req->headers->from_hash(ref $_[0] eq 'HASH' ? $_[0] : {@_});
 
   return $tx unless wantarray;
-  return $tx, $cb;
+  $tx, $cb;
 }
 
 sub build_websocket_tx {
@@ -208,37 +208,38 @@ sub build_websocket_tx {
     ->client_handshake;
 
   return $tx unless wantarray;
-  return $tx, $cb;
+  $tx, $cb;
 }
 
 # "The only thing I asked you to do for this party was put on clothes,
 #  and you didn't do it."
 sub delete {
   my $self = shift;
-  return $self->start($self->build_tx('DELETE', @_));
+  $self->start($self->build_tx('DELETE', @_));
 }
 
 sub detect_proxy {
   my $self = shift;
 
+  # Uppercase gets priority
   $self->http_proxy($ENV{HTTP_PROXY}   || $ENV{http_proxy});
   $self->https_proxy($ENV{HTTPS_PROXY} || $ENV{https_proxy});
   if (my $no = $ENV{NO_PROXY} || $ENV{no_proxy}) {
     $self->no_proxy([split /,/, $no]);
   }
 
-  return $self;
+  $self;
 }
 
 # "'What are you lookin at?' - the innocent words of a drunken child."
 sub get {
   my $self = shift;
-  return $self->start($self->build_tx('GET', @_));
+  $self->start($self->build_tx('GET', @_));
 }
 
 sub head {
   my $self = shift;
-  return $self->start($self->build_tx('HEAD', @_));
+  $self->start($self->build_tx('HEAD', @_));
 }
 
 sub need_proxy {
@@ -251,19 +252,19 @@ sub need_proxy {
   $host =~ /\Q$_\E$/ and return for @$no;
 
   # Proxy needed
-  return 1;
+  1;
 }
 
 # "Olive oil? Asparagus? If your mother wasn't so fancy,
 #  we could just shop at the gas station like normal people."
 sub post {
   my $self = shift;
-  return $self->start($self->build_tx('POST', @_));
+  $self->start($self->build_tx('POST', @_));
 }
 
 sub post_form {
   my $self = shift;
-  return $self->start($self->build_form_tx(@_));
+  $self->start($self->build_form_tx(@_));
 }
 
 # "And I gave that man directions, even though I didn't know the way,
@@ -278,8 +279,8 @@ sub put {
 sub start {
   my ($self, $tx, $cb) = @_;
 
-  # Default loop
-  $self->{_loop} ||= $self->ioloop;
+  # Blocking loop
+  my $loop = $self->{_loop} ||= $self->ioloop;
 
   # Non-blocking
   if ($cb) {
@@ -300,40 +301,38 @@ sub start {
   $self->_start_tx($tx, sub { $tx = $_[1] });
 
   # Start loop
-  $self->{_loop}->start;
+  $loop->start;
 
   # Cleanup
-  $self->{_loop}->one_tick(0);
+  $loop->one_tick(0);
 
-  return $tx;
+  $tx;
 }
 
 # "It's like my dad always said: eventually, everybody gets shot."
 sub test_server {
   my ($self, $protocol) = @_;
 
-  # Server
+  # Start test server
   unless ($self->{_port}) {
     my $loop = $self->{_loop} || $self->ioloop;
-
     my $server = $self->{_server} =
       Mojo::Server::Daemon->new(ioloop => $loop, silent => 1);
     my $port = $self->{_port} = $loop->generate_port;
     die "Couldn't find a free TCP port for testing.\n" unless $port;
-
     $self->{_protocol} = $protocol ||= 'http';
     $server->listen(["$protocol://*:$port"]);
     $server->prepare_ioloop;
   }
 
-  # Application
+  # Prepare application for testing
   my $server = $self->{_server};
   delete $server->{app};
   my $app = $self->app;
   ref $app ? $server->app($app) : $server->app_class($app);
   $self->log($server->app->log);
 
-  return $self->{_port};
+  $self->{_port};
 }
 
 # "Are we there yet?
@@ -388,7 +387,7 @@ sub _cache {
   }
   $self->{_cache} = \@cache;
 
-  return $result;
+  $result;
 }
 
 sub _cleanup {
@@ -417,15 +416,12 @@ sub _close { shift->_handle(pop, 1) }
 #  Uh, second word, chief."
 sub _connect {
   my ($self, $tx, $cb) = @_;
-  my $loop = $self->{_loop};
-
-  # Info
-  my $id = $tx->connection;
-  my ($scheme, $address, $port) = $self->_tx_info($tx);
-
-  weaken $self;
 
   # Keep alive connection
+  weaken $self;
+  my $loop = $self->{_loop};
+  my $id   = $tx->connection;
+  my ($scheme, $address, $port) = $self->_tx_info($tx);
   $id ||= $self->_cache("$scheme:$address:$port");
   if ($id && !ref $id) {
     warn "KEEP ALIVE CONNECTION ($scheme:$address:$port)\n" if DEBUG;
@@ -463,20 +459,19 @@ sub _connect {
   $loop->on_error($id => sub { $self->_error(@_) });
   $loop->on_read($id => sub { $self->_read(@_) });
 
-  return $id;
+  $id;
 }
 
 # "Hey, Weener Boy... where do you think you're going?"
 sub _connect_proxy {
   my ($self, $old, $cb) = @_;
 
-  my $req = $old->req;
-  my $url = $req->url;
-
   # No proxy
+  my $req = $old->req;
   return unless my $proxy = $req->proxy;
 
   # WebSocket and/or HTTPS
+  my $url = $req->url;
   return
     unless ($req->headers->upgrade || '') eq 'websocket'
     || ($url->scheme || '') eq 'https';
@@ -520,7 +515,7 @@ sub _connect_proxy {
     }
   );
 
-  return 1;
+  1;
 }
 
 # "I don't mind being called a liar when I'm lying, or about to lie,
@@ -528,11 +523,10 @@ sub _connect_proxy {
 sub _connected {
   my ($self, $id) = @_;
 
+  # Store connection information in transaction
   my $loop = $self->{_loop};
   my $tx   = $self->{_cs}->{$id}->{tx};
   $tx->connection($id);
-
-  # Store connection information in transaction
   my $local = $loop->local_info($id);
   $tx->local_address($local->{address});
   $tx->local_port($local->{port});
@@ -576,13 +570,13 @@ sub _drop {
 sub _error {
   my ($self, $loop, $id, $error) = @_;
 
-  # Transaction
+  # Store error in response
   if (my $tx = $self->{_cs}->{$id}->{tx}) { $tx->res->error($error) }
 
-  # Log
+  # Log error
   $self->log->error($error);
 
-  # Finished
+  # Finish connection
   $self->_handle($id, $error);
 }
 
@@ -606,10 +600,9 @@ sub _finish_tx {
 sub _handle {
   my ($self, $id, $close) = @_;
 
+  # WebSocket
   my $c   = $self->{_cs}->{$id};
   my $old = $c->{tx};
-
-  # WebSocket
   if ($old && $old->is_websocket) {
 
     # Finish transaction
@@ -622,17 +615,17 @@ sub _handle {
   # Upgrade connection to WebSocket
   elsif ($old && (my $new = $self->_upgrade($id))) {
 
-    # Finish
+    # Finish transaction
     $self->_finish_tx($new, $c->{cb});
 
-    # Leftovers
+    # Parse leftovers
     $new->client_read($old->res->leftovers);
   }
 
   # Normal connection
   else {
 
-    # Cleanup
+    # Cleanup connection
     $self->_drop($id, $close);
 
     # Idle connection
@@ -718,10 +711,10 @@ sub _redirect {
   $self->{_cs}->{$new_id}->{redirects} = $r + 1;
 
   # Redirecting
-  return 1;
+  1;
 }
 
-# "It's greeat! We can do *anything* now that Science has invented Magic."
+# "It's great! We can do *anything* now that Science has invented Magic."
 sub _start_tx {
   my ($self, $tx, $cb) = @_;
 
@@ -742,11 +735,10 @@ sub _start_tx {
   # Detect proxy
   $self->detect_proxy if $ENV{MOJO_PROXY};
 
+  # Proxy
   my $req    = $tx->req;
   my $url    = $req->url;
   my $scheme = $url->scheme || '';
-
-  # Proxy
   if ($self->need_proxy($url->host)) {
 
     # HTTP proxy
@@ -781,7 +773,7 @@ sub _start_tx {
   $self->{_processing} ||= 0;
   $self->{_processing} += 1;
 
-  return $id;
+  $id;
 }
 
 sub _switch_blocking {
@@ -791,9 +783,8 @@ sub _switch_blocking {
   croak 'Non-blocking requests in progress' if $self->{_processing};
   warn "SWITCHING TO BLOCKING MODE\n" if DEBUG;
 
-  $self->_cleanup;
-
   # Normal loop
+  $self->_cleanup;
   $self->{_loop} = $self->ioloop;
   $self->{_nb}   = 0;
 }
@@ -805,9 +796,8 @@ sub _switch_non_blocking {
   croak 'Blocking request in progress' if $self->{_processing};
   warn "SWITCHING TO NON-BLOCKING MODE\n" if DEBUG;
 
-  $self->_cleanup;
-
   # Global loop
+  $self->_cleanup;
   $self->{_loop} = Mojo::IOLoop->singleton;
   $self->{_nb}   = 1;
 }
@@ -815,13 +805,12 @@ sub _switch_non_blocking {
 sub _tx_info {
   my ($self, $tx) = @_;
 
+  # Proxy info
   my $req    = $tx->req;
   my $url    = $req->url;
   my $scheme = $url->scheme || 'http';
   my $host   = $url->ihost;
   my $port   = $url->port;
-
-  # Proxy info
   if (my $proxy = $req->proxy) {
     $scheme = $proxy->scheme;
     $host   = $proxy->ihost;
@@ -831,17 +820,16 @@ sub _tx_info {
   # Default port
   $port ||= $scheme eq 'https' ? 443 : 80;
 
-  return ($scheme, $host, $port);
+  ($scheme, $host, $port);
 }
 
 # "Once the government approves something, it's no longer immoral!"
 sub _upgrade {
   my ($self, $id) = @_;
 
+  # No upgrade request
   my $c   = $self->{_cs}->{$id};
   my $old = $c->{tx};
-
-  # No upgrade request
   return unless $old->req->headers->upgrade;
 
   # Handshake failed
@@ -864,7 +852,7 @@ sub _upgrade {
   weaken $self;
   $new->on_resume(sub { $self->_write($id) });
 
-  return $new;
+  $new;
 }
 
 # "Oh well. At least we'll die doing what we love: inhaling molten rock."
@@ -1323,10 +1311,13 @@ Note that this method is EXPERIMENTAL and might change without warning!
 
 Open a non-blocking WebSocket connection with transparent handshake.
 
-  $ua->websocket('ws://localhost:3000' => sub {
+  $ua->websocket('ws://localhost:3000/echo' => sub {
     my $tx = pop;
-    $tx->on_finish(sub { Mojo::IOLoop->stop });
-    $tx->on_message(sub { say pop });
+    $tx->on_finish(sub  { Mojo::IOLoop->stop });
+    $tx->on_message(sub {
+      my ($tx, $message) = @_;
+      print "$message\n";
+    });
     $tx->send_message('Hi!');
   });
   Mojo::IOLoop->start;
@@ -376,7 +376,7 @@ sub get_line {
   my $line = substr $_[0], 0, $pos + 1, '';
   $line =~ s/\x0d?\x0a$//;
 
-  return $line;
+  $line;
 }
 
 sub hmac_md5_sum { _hmac(\&_md5, @_) }
@@ -384,7 +384,6 @@ sub hmac_md5_sum { _hmac(\&_md5, @_) }
 sub hmac_sha1_sum { _hmac(\&_sha1, @_) }
 
 sub html_escape {
-
   my $escaped = '';
   for (1 .. length $_[0]) {
 
@@ -398,32 +397,37 @@ sub html_escape {
   $_[0] = $escaped;
 }
 
+# "Daddy, I'm scared. Too scared to even wet my pants.
+#  Just relax and it'll come, son."
 sub html_unescape {
-
-  # Unescape
   $_[0] =~ s/
     &
     (?:
-      \#(\d{1,7})             # Number
-      |
-      ([A-Za-z]{1,8})         # Named
+      \#
+      (
+        (?:
+          \d{1,7}             # Number
+          |
+          x[0-9A-Fa-f]{1,6}   # Hex
+        )
+      )
       |
-      \#x([0-9A-Fa-f]{1,6})   # Hex
+      ([A-Za-z]{1,8})         # Name
     )
     ;
-    /_unescape($1, $2, $3)/gex;
+  /_unescape($1, $2)/gex;
 }
 
 sub md5_bytes {
   my $data = shift;
   utf8::encode $data if utf8::is_utf8 $data;
-  return _md5($data);
+  _md5($data);
 }
 
 sub md5_sum {
   my $data = shift;
   utf8::encode $data if utf8::is_utf8 $data;
-  return Digest::MD5::md5_hex($data);
+  Digest::MD5::md5_hex($data);
 }
 
 sub punycode_decode {
@@ -449,14 +453,12 @@ sub punycode_decode {
       # Digit
       my $digit = ord substr $_[0], 0, 1, '';
       $digit = $digit < 0x40 ? $digit + (26 - 0x30) : ($digit & 0x1f) - 1;
-
       $i += $digit * $w;
       my $t = $k - $bias;
       $t =
           $t < PUNYCODE_TMIN ? PUNYCODE_TMIN
         : $t > PUNYCODE_TMAX ? PUNYCODE_TMAX
         :                      $t;
-
       last if $digit < $t;
 
       $w *= (PUNYCODE_BASE - $t);
@@ -464,7 +466,6 @@ sub punycode_decode {
 
     # Bias
     $bias = _adapt($i - $oldi, @output + 1, $oldi == 0);
-
     $n += $i / (@output + 1);
     $i = $i % (@output + 1);
 
@@ -472,12 +473,14 @@ sub punycode_decode {
     splice @output, $i, 0, chr($n);
     $i++;
   }
+
   $_[0] = join '', @output;
 }
 
 sub punycode_encode {
   use integer;
 
+  # Defaults
   my $output = $_[0];
   my $len    = length $_[0];
 
@@ -525,7 +528,6 @@ sub punycode_encode {
               $t < PUNYCODE_TMIN ? PUNYCODE_TMIN
             : $t > PUNYCODE_TMAX ? PUNYCODE_TMAX
             :                      $t;
-
           last if $q < $t;
 
           # Code point for digit "t"
@@ -540,7 +542,6 @@ sub punycode_encode {
 
         # Bias
         $bias = _adapt($delta, $h + 1, $h == $b);
-
         $delta = 0;
         $h++;
       }
@@ -549,6 +550,7 @@ sub punycode_encode {
     $delta++;
     $n++;
   }
+
   $_[0] = $output;
 }
 
@@ -569,7 +571,7 @@ sub quote {
 sub sha1_bytes {
   my $data = shift;
   utf8::encode $data if utf8::is_utf8 $data;
-  return _sha1($data);
+  _sha1($data);
 }
 
 sub sha1_sum {
@@ -579,7 +581,7 @@ Please install it manually or upgrade Perl to at least version 5.10.
 EOF
   my $data = shift;
   utf8::encode $data if utf8::is_utf8 $data;
-  return Digest::SHA::sha1_hex($data);
+  Digest::SHA::sha1_hex($data);
 }
 
 sub trim {
@@ -616,8 +618,6 @@ sub url_escape {
 
 sub url_unescape {
   return if index($_[0], '%') == -1;
-
-  # Unescape
   $_[0] =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/ge;
 }
 
@@ -638,11 +638,8 @@ sub _adapt {
   my ($delta, $numpoints, $firsttime) = @_;
 
   use integer;
-
-  # Delta
   $delta = $firsttime ? $delta / PUNYCODE_DAMP : $delta / 2;
   $delta += $delta / $numpoints;
-
   my $k = 0;
   while ($delta > ((PUNYCODE_BASE - PUNYCODE_TMIN) * PUNYCODE_TMAX) / 2) {
     $delta /= PUNYCODE_BASE - PUNYCODE_TMIN;
@@ -664,7 +661,7 @@ sub _hmac {
   # HMAC
   my $ipad = $secret ^ (chr(0x36) x 64);
   my $opad = $secret ^ (chr(0x5c) x 64);
-  return unpack 'H*', $_[0]->($opad . $_[0]->($ipad . $_[1]));
+  unpack 'H*', $_[0]->($opad . $_[0]->($ipad . $_[1]));
 }
 
 # Helper for md5_bytes
@@ -681,19 +678,11 @@ EOF
 
 # Helper for html_unescape
 sub _unescape {
-  my ($num, $entitie, $hex) = @_;
-
-  # Named to number
-  if (defined $entitie) { $num = $ENTITIES{$entitie} }
-
-  # Hex to number
-  elsif (defined $hex) { $num = hex $hex }
-
-  # Number
-  return pack 'U', $num if $num;
-
-  # Unknown entitie
-  return "&$entitie;";
+  if ($_[0]) {
+    return chr hex $_[0] if substr($_[0], 0, 1) eq 'x';
+    return chr $_[0];
+  }
+  exists $ENTITIES{$_[1]} ? chr $ENTITIES{$_[1]} : "&$_[1];";
 }
 
 1;
@@ -24,21 +24,21 @@ has ua => sub {
   my $ua = Mojo::UserAgent->new(app => $self, log => $self->log);
   weaken $ua->{app};
 
-  return $ua;
+  $ua;
 };
 
 # "Oh, so they have internet on computers now!"
 sub new {
   my $self = shift->SUPER::new(@_);
 
-  # Home
+  # Detect home directory
   $self->home->detect(ref $self);
 
   # Log directory
   $self->log->path($self->home->rel_file('log/mojo.log'))
     if -w $self->home->rel_file('log');
 
-  return $self;
+  $self;
 }
 
 # "D’oh."
@@ -105,15 +105,15 @@ The logging layer of your application, by default a L<Mojo::Log> object.
   my $cb = $app->on_transaction;
   $app   = $app->on_transaction(sub {...});
 
-The transaction builder callback, by default it builds a
-L<Mojo::Transaction::HTTP> object.
+Callback to be invoked when a new transaction is needed, by default it builds
+a L<Mojo::Transaction::HTTP> object.
 
 =head2 C<on_websocket>
 
   my $cb = $app->on_websocket;
   $app   = $app->on_websocket(sub {...});
 
-The websocket handshake callback, by default it builds a
+Callback to be invoked for WebSocket handshakes, by default it builds a
 L<Mojo::Transaction::WebSocket> object and handles the response for the
 handshake request.
 
@@ -23,7 +23,7 @@ sub run {
   GetOptions(nph => sub { $cgi->nph(1) });
   $cgi->run;
 
-  return $self;
+  $self;
 }
 
 1;
@@ -20,8 +20,6 @@ These options are available:
                           defaults to http://*:3000.
   --proxy                 Activate reverse proxy support, defaults to the
                           value of MOJO_REVERSE_PROXY.
-  --reload                Automatically reload application when the source
-                          code changes.
   --requests <number>     Set maximum number of requests per keep-alive
                           connection, defaults to 100.
   --user <name>           Set user name for process.
@@ -44,7 +42,6 @@ sub run {
     'keepalive=i' => sub { $daemon->keep_alive_timeout($_[1]) },
     'listen=s'    => \@listen,
     'proxy' => sub { $ENV{MOJO_REVERSE_PROXY} = 1 },
-    reload  => sub { $ENV{MOJO_RELOAD}        = 1 },
     'requests=i'  => sub { $daemon->max_requests($_[1]) },
     'user=s'      => sub { $daemon->user($_[1]) },
     'websocket=i' => sub { $daemon->websocket_timeout($_[1]) }
@@ -53,7 +50,7 @@ sub run {
   $daemon->listen(\@listen) if @listen;
   $daemon->run;
 
-  return $self;
+  $self;
 }
 
 1;
@@ -38,7 +38,7 @@ sub run {
   my $result = eval "package main; sub app { \$app }; $code";
   print "$result\n" if $verbose && defined $result;
   die $@ if $@;
-  return $result;
+  $result;
 }
 
 1;
@@ -15,7 +15,7 @@ sub run {
   my $self    = shift;
   my $fastcgi = Mojo::Server::FastCGI->new;
   $fastcgi->run;
-  return $self;
+  $self;
 }
 
 1;
@@ -19,9 +19,8 @@ Your application name has to be a well formed (camel case) Perl module name
 like "MyApp".
 EOF
 
-  my $name = $self->class_to_file($class);
-
   # Script
+  my $name = $self->class_to_file($class);
   $self->render_to_rel_file('mojo', "$name/script/$name", $class);
   $self->chmod_file("$name/script/$name", 0744);
 
@@ -17,7 +17,6 @@ sub run {
   my $class = $ENV{MOJO_APP} || 'MyApp';
   my $path  = $self->class_to_path($class);
   my $name  = $self->class_to_file($class);
-
   $self->render_to_rel_file('makefile', 'Makefile.PL', $class, $path, $name);
   $self->chmod_file('Makefile.PL', 0744);
 }
@@ -40,6 +40,7 @@ EOF
 sub run {
   my $self = shift;
 
+  # Options
   local @ARGV = @_ if @_;
   my $method = 'GET';
   my @headers;
@@ -61,11 +62,10 @@ sub run {
     $headers->{$1} = $2;
   }
 
-  # URL
+  # URL and selector
   my $url = shift @ARGV;
   die $self->usage unless $url;
   decode 'UTF-8', $url;
-
   my $selector = shift @ARGV;
 
   # Fresh user agent
@@ -151,7 +151,7 @@ sub run {
   # Select
   $self->_select($buffer, $charset, $selector) if $selector;
 
-  return $self;
+  $self;
 }
 
 sub _select {
@@ -48,7 +48,7 @@ sub run {
     $self->write_file($path, $content);
   }
 
-  return $self;
+  $self;
 }
 
 1;
@@ -20,7 +20,7 @@ sub run {
   $psgi->app;
 
   # Return app callback
-  return sub { $psgi->run(@_) };
+  sub { $psgi->run(@_) };
 }
 
 1;
@@ -14,17 +14,16 @@ EOF
 sub run {
   my $self = shift;
 
+  # Check if application has routes
   my $app = Mojo::Server->new->app;
   die "Application has no routes.\n" unless $app->can('routes');
 
-  # Walk
+  # Walk and draw
   my $routes = [];
   $self->_walk($_, 0, $routes) for @{$app->routes->children};
-
-  # Draw
   $self->_draw($routes);
 
-  return $self;
+  $self;
 }
 
 sub _draw {
@@ -56,7 +56,7 @@ sub run {
   # Run tests
   runtests(@tests);
 
-  return $self;
+  $self;
 }
 
 1;
@@ -69,7 +69,7 @@ OPTIONAL
 $message
 EOF
 
-  return $self;
+  $self;
 }
 
 1;
@@ -8,6 +8,7 @@ use Getopt::Long qw/GetOptions :config pass_through/;
 has hint => <<"EOF";
 
 These options are available for all commands:
+    --help          Get more information on a specific command.
     --home <path>   Path to your applications home directory, defaults to
                     the value of MOJO_HOME or auto detection.
     --mode <name>   Run mode of your application, defaults to the value of
@@ -17,9 +18,10 @@ See '$0 help COMMAND' for more information on a specific command.
 EOF
 has namespaces => sub { [qw/Mojolicious::Command Mojo::Command/] };
 
-# Command line options for MOJO_HOME and MOJO_MODE
+# Command line options for MOJO_HELP, MOJO_HOME and MOJO_MODE
 BEGIN {
   GetOptions(
+    'help|h' => sub { $ENV{MOJO_HELP} = 1 },
     'home=s' => sub { $ENV{MOJO_HOME} = $_[1] },
     'mode=s' => sub { $ENV{MOJO_MODE} = $_[1] }
   ) unless Mojo::Command->detect;
@@ -53,116 +55,116 @@ These commands are available by default.
 
 =head2 C<help>
 
-  mojo
-  mojo help
+  % mojo
+  % mojo help
 
 List available commands with short descriptions.
 
-  mojo help <command>
+  % mojo help <command>
 
 List available options for the command with short descriptions.
 
 =head2 C<cgi>
 
-  mojo cgi
-  script/myapp cgi
+  % mojo cgi
+  % script/myapp cgi
 
 Start application with CGI backend.
 
 =head2 C<daemon>
 
-  mojo daemon
-  script/myapp daemon
+  % mojo daemon
+  % script/myapp daemon
 
 Start application with standalone HTTP 1.1 server backend.
 
 =head2 C<eval>
 
-  mojo eval 'print app->home'
-  script/myapp eval 'print app->home'
+  % mojo eval 'print app->home'
+  % script/myapp eval 'print app->home'
 
 Run code against application.
 
 =head2 C<fastcgi>
 
-  mojo fastcgi
-  script/myapp fastcgi
+  % mojo fastcgi
+  % script/myapp fastcgi
 
 Start application with FastCGI backend.
 
 =head2 C<generate>
 
-  mojo generate
-  mojo generate help
+  % mojo generate
+  % mojo generate help
 
 List available generator commands with short descriptions.
 
-  mojo generate help <generator>
+  % mojo generate help <generator>
 
 List available options for generator command with short descriptions.
 
 =head2 C<generate app>
 
-  mojo generate app <AppName>
+  % mojo generate app <AppName>
 
 Generate application directory structure for a fully functional
 L<Mojolicious> application.
 
 =head2 C<generate gitignore>
 
-  mojo generate gitignore
+  % mojo generate gitignore
 
 Generate C<.gitignore> file.
 
 =head2 C<generate hypnotoad>
 
-  mojo generate hypnotoad
+  % mojo generate hypnotoad
 
 Generate C<hypnotoad.conf> file.
 
 =head2 C<generate lite_app>
 
-  mojo generate lite_app
+  % mojo generate lite_app
 
 Generate a fully functional L<Mojolicious::Lite> application.
 
 =head2 C<generate makefile>
 
-  mojo generate makefile
+  % mojo generate makefile
 
 Generate C<Makefile.PL> file for application.
 
 =head2 C<get>
 
-  mojo get http://mojolicio.us
-  script/myapp get /foo
+  % mojo get http://mojolicio.us
+  % script/myapp get /foo
 
 Perform GET request to remote host or local application.
 
 =head2 C<inflate>
 
-  myapp.pl inflate
+  % myapp.pl inflate
 
 Turn embedded files from the C<DATA> section into real files.
 
 =head2 C<routes>
 
-  myapp.pl routes
-  script/myapp routes
+  % myapp.pl routes
+  % script/myapp routes
 
 List application routes.
 
 =head2 C<test>
 
-  mojo test
-  script/myapp test
-  script/myapp test t/foo.t
+  % mojo test
+  % script/myapp test
+  % script/myapp test t/foo.t
 
 Runs application tests from the C<t> directory.
 
 =head2 C<version>
 
-  mojo version
+  % mojo version
 
 List version information for installed core and optional modules, very useful
 for debugging.
@@ -59,7 +59,7 @@ sub AUTOLOAD {
   # Call helper
   Carp::croak(qq/Can't locate object method "$method" via package "$package"/)
     unless my $helper = $self->app->renderer->helpers->{$method};
-  return $self->$helper(@_);
+  $self->$helper(@_);
 }
 
 sub DESTROY { }
@@ -97,7 +97,7 @@ sub cookie {
 
   # Request cookies
   my @cookies = $self->req->cookie($name);
-  return map { $_->value } @cookies;
+  map { $_->value } @cookies;
 }
 
 # "Something's wrong, she's not responding to my poking stick."
@@ -145,7 +145,7 @@ sub flash {
   my $values = exists $_[1] ? {@_} : $_[0];
   $session->{new_flash} = {%$flash, %$values};
 
-  return $self;
+  $self;
 }
 
 # "My parents may be evil, but at least they're stupid."
@@ -154,9 +154,6 @@ sub on_finish {
   $self->tx->on_finish(sub { shift and $self->$cb(@_) });
 }
 
-# "Stop being such a spineless jellyfish!
-#  You know full well I'm more closely related to the sea cucumber.
-#  Not where it counts."
 sub on_message {
   my $self = shift;
 
@@ -167,7 +164,7 @@ sub on_message {
   $tx->on_message(sub { shift and $self->$cb(@_) });
   $self->rendered(101);
 
-  return $self;
+  $self;
 }
 
 # "Just make a simple cake. And this time, if someone's going to jump out of
@@ -195,7 +192,7 @@ sub param {
   return $p->{$name} if !$RESERVED{$name} && exists $p->{$name};
 
   # Param value
-  return $self->req->param($name);
+  $self->req->param($name);
 }
 
 # "Is there an app for kissing my shiny metal ass?
@@ -209,7 +206,7 @@ sub redirect_to {
   $headers->content_length(0);
   $self->rendered(302);
 
-  return $self;
+  $self;
 }
 
 # "Mamma Mia! The cruel meatball of war has rolled onto our laps and ruined
@@ -224,10 +221,9 @@ sub render {
     return '';
   }
 
-  # Template as single argument
+  # Template may be first argument
   my $template;
   $template = shift if @_ % 2 && !ref $_[0];
-
   my $args = ref $_[0] ? $_[0] : {@_};
 
   # Template
@@ -256,11 +252,7 @@ sub render {
     $app->plugins->run_hook_reverse(before_render => $self, $args);
   }
   my ($output, $type) = $app->renderer->render($self, $args);
-
-  # Failed
   return unless defined $output;
-
-  # Partial
   return $output if $args->{partial};
 
   # Prepare response
@@ -270,8 +262,7 @@ sub render {
   $headers->content_type($type) unless $headers->content_type;
   $self->rendered($stash->{status});
 
-  # Success
-  return 1;
+  1;
 }
 
 sub render_content {
@@ -304,7 +295,7 @@ sub render_content {
   # Get
   $content = $c->{$name};
   $content = '' unless defined $content;
-  return Mojo::ByteStream->new("$content");
+  Mojo::ByteStream->new("$content");
 }
 
 sub render_data { shift->render(data => shift, @_) }
@@ -328,6 +319,7 @@ sub render_exception {
     $snapshot->{$key} = $value;
   }
 
+  # Mode specific template
   my $mode    = $self->app->mode;
   my $options = {
     template         => "exception.$mode",
@@ -338,8 +330,6 @@ sub render_exception {
     exception        => $e,
     'mojo.exception' => 1
   };
-
-  # Mode specific template
   unless ($self->render($options)) {
 
     # Template
@@ -347,8 +337,8 @@ sub render_exception {
     unless ($self->render($options)) {
 
       # Inline template
-      delete $options->{layout};
-      delete $options->{extends};
+      delete $stash->{layout};
+      delete $stash->{extends};
       delete $options->{template};
       $options->{inline} =
         $mode eq 'development' ? $DEVELOPMENT_EXCEPTION : $EXCEPTION;
@@ -374,7 +364,7 @@ sub render_json {
   my $json = shift;
   my $args = ref $_[0] ? $_[0] : {@_};
   $args->{json} = $json;
-  return $self->render($args);
+  $self->render($args);
 }
 
 sub render_later { shift->stash->{'mojo.rendered'} = 1 }
@@ -396,6 +386,7 @@ sub render_not_found {
     ? $self->url_for('/perldoc')
     : 'http://mojolicio.us/perldoc';
 
+  # Mode specific template
   my $mode    = $self->app->mode;
   my $options = {
     template         => "not_found.$mode",
@@ -404,8 +395,6 @@ sub render_not_found {
     guide            => $guide,
     'mojo.not_found' => 1
   };
-
-  # Mode specific template
   unless ($self->render($options)) {
 
     # Template
@@ -434,16 +423,21 @@ sub render_partial {
   $args->{template} = $template if defined $template;
   $args->{partial} = 1;
 
-  return Mojo::ByteStream->new($self->render($args));
+  Mojo::ByteStream->new($self->render($args));
 }
 
 sub render_static {
   my ($self, $file) = @_;
+
   my $app = $self->app;
-  $app->static->serve($self, $file)
-    and $app->log->debug(
-    qq/Static file "$file" not found, public directory missing?/);
+  unless ($app->static->serve($self, $file)) {
+    $app->log->debug(
+      qq/Static file "$file" not found, public directory missing?/);
+    return;
+  }
   $self->rendered;
+
+  1;
 }
 
 sub render_text { shift->render(text => shift, @_) }
@@ -466,13 +460,13 @@ sub rendered {
   unless ($stash->{'mojo.finished'}) {
     $res->code(200) unless $res->code;
     my $app = $self->app;
-    $app->sessions->store($self);
     $app->plugins->run_hook_reverse(after_dispatch => $self);
+    $app->sessions->store($self);
     $stash->{'mojo.finished'} = 1;
   }
   $self->tx->resume;
 
-  return $self;
+  $self;
 }
 
 sub req { shift->tx->req }
@@ -487,7 +481,7 @@ sub send_message {
   $tx->send_message($message, sub { shift and $self->$cb(@_) if $cb });
   $self->rendered(101);
 
-  return $self;
+  $self;
 }
 
 # "Why am I sticky and naked? Did I miss something fun?"
@@ -511,7 +505,7 @@ sub session {
   my $values = exists $_[1] ? {@_} : $_[0];
   $stash->{'mojo.session'} = {%$session, %$values};
 
-  return $self;
+  $self;
 }
 
 sub signed_cookie {
@@ -555,7 +549,7 @@ sub signed_cookie {
     else { $self->app->log->debug(qq/Cookie "$name" not signed./) }
   }
 
-  return wantarray ? @results : $results[0];
+  wantarray ? @results : $results[0];
 }
 
 # "All this knowledge is giving me a raging brainer."
@@ -577,7 +571,7 @@ sub stash {
     $self->{stash}->{$key} = $values->{$key};
   }
 
-  return $self;
+  $self;
 }
 
 sub ua { shift->app->ua }
@@ -611,7 +605,18 @@ sub url_for {
 
   # Relative URL
   my $path = $url->path;
-  if ($target =~ /^\//) { $url->parse($target) }
+  if ($target =~ /^\//) {
+    if (my $e = $self->stash->{path}) {
+      my $real = $req->url->path->to_abs_string;
+      Mojo::Util::url_unescape($real);
+      my $backup = $real;
+      Mojo::Util::decode('UTF-8', $real);
+      $real = $backup unless defined $real;
+      $real =~ s/\/?$e$/$target/;
+      $target = $real;
+    }
+    $url->parse($target);
+  }
 
   # Route
   else {
@@ -627,7 +632,7 @@ sub url_for {
   unshift @{$path->parts}, @{$base_path->parts};
   $base_path->parts([]);
 
-  return $url;
+  $url;
 }
 
 # "I wax my rocket every day!"
@@ -641,7 +646,7 @@ sub write {
   $self->res->write($chunk, sub { shift and $self->$cb(@_) if $cb });
   $self->rendered;
 
-  return $self;
+  $self;
 }
 
 sub write_chunk {
@@ -654,7 +659,7 @@ sub write_chunk {
   $self->res->write_chunk($chunk, sub { shift and $self->$cb(@_) if $cb });
   $self->rendered;
 
-  return $self;
+  $self;
 }
 
 1;
@@ -741,21 +746,20 @@ Data storage persistent for the next request, stored in the session.
 
   $c->on_finish(sub {...});
 
-Callback signaling that the transaction has been finished.
+Callback to be invoked when the transaction has been finished.
 
   $c->on_finish(sub {
-    my $self = shift;
+    my $c = shift;
   });
 
 =head2 C<on_message>
 
   $c = $c->on_message(sub {...});
 
-Receive messages via WebSocket, only works if there is currently a WebSocket
-connection in progress.
+Callback to be invoked when new WebSocket messages arrive.
 
   $c->on_message(sub {
-    my ($self, $message) = @_;
+    my ($c, $message) = @_;
   });
 
 =head2 C<param>
@@ -868,8 +872,8 @@ Same as C<render> but returns the rendered result.
 
 =head2 C<render_static>
 
-  $c->render_static('images/logo.png');
-  $c->render_static('../lib/MyApp.pm');
+  my $success = $c->render_static('images/logo.png');
+  my $success = $c->render_static('../lib/MyApp.pm');
 
 Render a static file using L<Mojolicious::Static> relative to the
 C<public> directory of your application.
@@ -888,8 +892,8 @@ C<text/html;charset=UTF-8> by default.
 
 =head2 C<rendered>
 
-  $c->rendered;
-  $c->rendered(302);
+  $c = $c->rendered;
+  $c = $c->rendered(302);
 
 Finalize response and run C<after_dispatch> plugin hook.
 
@@ -990,12 +994,19 @@ once all data has been written to the kernel send buffer or equivalent.
 
   # Keep connection alive (with Content-Length header)
   $c->res->headers->content_length(6);
-  $c->write('Hel', sub { shift->write('lo!') });
+  $c->write('Hel', sub {
+    my $c = shift;
+    $c->write('lo!')
+  });
 
   # Close connection when done (without Content-Length header)
-  $c->write('Hel');
-  $c->write('lo!');
-  $c->finish;
+  $c->write('Hel', sub {
+    my $c = shift;
+    $c->write('lo!', sub {
+      my $c = shift;
+      $c->finish;
+    });
+  });
 
 =head2 C<write_chunk>
 
@@ -1009,9 +1020,13 @@ which doesn't require a C<Content-Length> header, the optional drain callback
 will be invoked once all data has been written to the kernel send buffer or
 equivalent.
 
-  $c->write_chunk('He');
-  $c->write_chunk('ll');
-  $c->finish('o!');
+  $c->write_chunk('He', sub {
+    my $c = shift;
+    $c->write_chunk('ll', sub {
+      my $c = shift;
+      $c->finish('o!');
+    });
+  });
 
 You can call C<finish> at any time to end the stream.
 
@@ -287,13 +287,6 @@ security reasons this is disabled by default.
 
   MOJO_PROXY=1
 
-=head2 C<MOJO_RELOAD>
-
-Enable L<Mojolicious> application reloading, changes to your application will
-be detected automatically so you don't have to restart the server manually.
-
-  MOJO_RELOAD=1
-
 =head2 C<MOJO_REVERSE_PROXY>
 
 Enable reverse proxy support for L<Mojolicious> application.
@@ -12,7 +12,7 @@ Cooking with L<Mojolicious>, recipes for every taste.
 Getting L<Mojolicious> and L<Mojolicious::Lite> applications running on
 different platforms.
 
-=head2 Builtin Server
+=head2 Built-in Server
 
 L<Mojolicious> contains a very portable HTTP 1.1 compliant web server.
 It is usually used during development but is solid and fast enough for small
@@ -47,7 +47,7 @@ of multiple cpu cores and copy-on-write.
   |- Mojo::Server::Daemon [3]
   `- Mojo::Server::Daemon [4]
 
-It is based on the normal builtin web server but optimized specifically for
+It is based on the normal built-in web server but optimized specifically for
 production environments out of the box.
 
   % hypnotoad script/myapp
@@ -68,7 +68,7 @@ connection, just by sending it a C<USR2> signal.
 
 =head2 Nginx
 
-One of the most popular setups these days is the builtin web server behind a
+One of the most popular setups these days is the built-in web server behind a
 Nginx reverse proxy.
 
   upstream myapp {
@@ -179,7 +179,20 @@ requests.
 
 =head2 Embedding
 
-You can also use the builtin web server to embed L<Mojolicious> applications
+From time to time you might want to reuse parts of L<Mojolicious>
+applications like configuration files, database connection or helpers for
+other scripts, with this little mock server you can just embed them.
+
+  use Mojo::Server;
+
+  # Load application with mock server
+  my $server = Mojo::Server->new;
+  my $app = $server->load_app('./myapp.pl');
+
+  # Access fully initialized application
+  print $app->static->root;
+
+You can also use the built-in web server to embed L<Mojolicious> applications
 into alien environments like foreign event loops.
 
   use Mojolicious::Lite;
@@ -337,14 +350,14 @@ Uploading a large file is even easier.
   # Upload file via POST and "multipart/form-data"
   my $ua = Mojo::UserAgent->new;
   $ua->post_form('mojolicio.us/upload',
-    {image => {file => '/Users/sri/hello.png'}});
+    {image => {file => '/home/sri/hello.png'}});
 
 And once again you don't have to worry about memory usage, all data will be
 streamed directly from the file.
 
   # Upload file via PUT
   my $ua     = Mojo::UserAgent->new;
-  my $asset  = Mojo::Asset::File->new(path => '/Users/sri/hello.png');
+  my $asset  = Mojo::Asset::File->new(path => '/home/sri/hello.png');
   my $tx     = $ua->build_tx(PUT => 'mojolicio.us/upload');
   $tx->req->content->asset($asset);
   $ua->start($tx);
@@ -410,56 +423,60 @@ You can just pick the parts that actually matter with the CSS3 selectors from
 L<Mojo::DOM>.
 
   % mojo get http://mojolicio.us 'head > title'
-  ...
 
 How about a list of all id attributes?
 
   % mojo get http://mojolicio.us '*' attr id
-  ...
 
 Or the text content of all header tags?
 
   % mojo get http://mojolicio.us 'h1, h2, h3' text
-  ...
 
 Maybe just the text of the third header?
 
   % mojo get http://mojolicio.us 'h1, h2, h3' 3 text
-  ...
 
 You can also extract all text from nested child elements.
 
   % mojo get http://mojolicio.us '#mojobar' all
-  ...
 
 The request can be customized as well.
 
   % mojo get --method post --content 'Hello!' http://mojolicio.us
-  ...
   % mojo get --header 'X-Bender: Bite my shiny metal ass!' http://google.com
-  ...
 
 You can follow redirects and view the headers for all messages.
 
   % mojo get --redirect --verbose http://reddit.com 'head > title'
-  ...
 
 This can be an invaluable tool for testing your applications.
 
   % ./myapp.pl get /welcome 'head > title'
-  ...
 
 =head1 HACKS
 
 Fun hacks you might not use very often but that might come in handy some day.
 
+=head2 Running Code Against Your Application
+
+Ever thought about running a quick oneliner against your L<Mojolicious>
+application to test something?
+Thanks to the C<eval> command you can do just that, the application instance
+itself can be accessed via C<app>.
+
+  % mojo generate lite_app
+  % ./myapp.pl eval 'print app->static->root, "\n"'
+
+The C<verbose> option will automatically print the return value to C<STDOUT>.
+
+  % ./myapp.pl eval -v 'app->static->root'
+
 =head2 Making Your Application Installable
 
 Ever thought about releasing your L<Mojolicious> application to CPAN?
 It's actually much easier than you might think.
 
   % mojo generate app
-  ...
   % cd my_mojolicious_app
   % mv public lib/MyMojoliciousApp/
   % mv templates lib/MyMojoliciousApp/
@@ -501,15 +518,10 @@ That's really everything, now you can package your application like any other
 CPAN module.
 
   % ./script/my_mojolicious_app generate makefile
-  ...
   % perl Makefile.PL
-  ...
   % make test
-  ...
   % make manifest
-  ...
   % make dist
-  ...
 
 =head2 Hello World
 
@@ -100,20 +100,14 @@ especially XS based modules due to its remarkable toolchain.
 With it you can even install modules straight from the source as you would do
 on a Unix based machine.
 
-=head2 Is it possible to run the builtin webserver on Windows?
+=head2 Is it possible to run the built-in webserver on Windows?
 
 It is!
-The builtin webserver is great way to run your L<Mojolicious> web application
-on any platform.
+The built-in webserver is great way to run your L<Mojolicious> web
+application on any platform.
 See L<Mojolicious::Guides::Cookbook> for more information about running and
 deploying L<Mojolicious> applications.
 
-Note that if you run your application with the C<--reload> option Windows
-will lock your files.
-A simple Windows editor like C<WordPad> will complain that the file has
-already been opened by a different proccess.
-More capable editors can handle this accordingly and force the change.
-
 =head2 Whats the easiest way to install L<Mojolicious> on UNIX?
 
 Quite possibly this oneliner.
@@ -166,10 +166,7 @@ organized CPAN distribution to maximize maintainability.
 Both application skeletons can be automatically generated.
 
   % mojo generate lite_app
-  ...
-
   % mojo generate app
-  ...
 
 =head2 Foundation
 
@@ -192,10 +189,10 @@ This will be the foundation for our login manager example application.
 
   app->start;
 
-The built-in web server makes working on your application a lot of fun thanks
-to automatic reloading.
+The built-in development web server makes working on your application a lot
+of fun thanks to automatic reloading.
 
-  % ./myapp.pl daemon --reload
+  % morbo myapp.pl
   Server available at http://127.0.0.1:3000.
 
 Just save your changes and they will be automatically in effect the next time
@@ -321,9 +318,7 @@ From now on you can always check your progress by running these unit tests
 against your application.
 
   % ./myapp.pl test
-  ...
   % ./myapp.pl test t/login.t
-  ...
 
 To make the tests less noisy and limit log output to just C<error> messages
 you can also add a line like this.
@@ -476,7 +471,6 @@ automatically turned into separate files in the C<templates> and C<public>
 directories.
 
   % ./myapp.pl inflate
-  ...
 
 Those directories always get priority, so inflating can also be a great way
 to allow your users to customize their applications.
@@ -546,7 +546,6 @@ C<DATA> section into actual files in the C<templates> and C<public>
 directories.
 
   % ./myapp.pl inflate
-  ...
 
 =head2 Customizing The Template Syntax
 
@@ -657,11 +657,18 @@ containing a C<handler> method accepting L<Mojolicious::Controller> objects.
 
   1;
 
-Because the remaining path always gets stored in the C<path> stash value, you
-could also just use it directly instead of C<detour>.
+You can also just use L<Mojolicious::Plugin::Mount> to mount whole
+self-contained applications under a prefix.
 
-  # /foo/*
-  $r->route('/foo/*path')->to('bar#', name => 'Mojo');
+  use Mojolicious::Lite;
+
+  # Whole application mounted under "/prefix"
+  plugin mount => {'/prefix' => '/home/sri/myapp.pl'};
+
+  # Normal route
+  get '/' => sub { shift->render_text('Hello World!') };
+
+  app->start;
 
 =head2 Application Plugins
 
@@ -13,7 +13,10 @@ updates.
 =head1 TUTORIAL
 
 A really fast and fun way to get started developing web applications with
-Mojolicious is the tutorial in L<Mojolicious::Lite>, you should take a look.
+Mojolicious is the tutorial in L<Mojolicious::Lite>.
+Almost everything you learn there can also be applied to normal
+L<Mojolicious> applications and is considered a prerequisite for the guides.
+You should definitely take a look!
 
 =head1 GUIDES
 
@@ -73,8 +76,8 @@ Minimalistic JSON implementation that just works.
 
 =item L<Mojo::Server::Daemon>
 
-Highly portable async io HTTP 1.1 and WebSocket server, perfect for
-development and testing.
+Highly portable async io HTTP 1.1 and WebSocket server with self-restart
+support through L<Mojo::Server::Morbo>, perfect for development and testing.
 
 =item L<Mojo::Server::Hypnotoad>
 
@@ -95,7 +98,7 @@ Countless portable and very convenient bytestream manipulation methods.
 
 =item L<Mojolicious::Commands>
 
-Pluggable command line system and the backbone of the C<mojo> script.
+Pluggable command line system and the backbone of the L<mojo> script.
 
 =item L<Test::Mojo>
 
@@ -45,10 +45,8 @@ sub import {
   $app->static->default_static_class($caller);
   $app->renderer->default_template_class($caller);
 
-  # Root
-  my $root = $routes;
-
   # Export
+  my $root = $routes;
   *{"${caller}::new"} = *{"${caller}::app"} = sub {$app};
   *{"${caller}::any"}    = sub { $routes->any(@_) };
   *{"${caller}::del"}    = sub { $routes->del(@_) };
@@ -153,10 +151,11 @@ customized to override normal C<@ARGV> use.
 
 =head2 Reloading
 
-Your application will automatically reload itself if you set the C<--reload>
-option, so you don't have to restart the server after every change.
+Your application will automatically reload itself if you start it with the
+C<morbo> development web server, so you don't have to restart the server
+after every change.
 
-  % ./myapp.pl daemon --reload
+  % morbo myapp.pl
   Server available at http://127.0.0.1:3000.
 
 =head2 Routes
@@ -276,8 +275,8 @@ delimited by the C<begin> and C<end> keywords.
   <!doctype html><html>
     <head><title>Sebastians Frameworks!</title></head>
     <body>
-      <%== $link->('http://mojolicio.us', 'Mojolicious') %>
-      <%== $link->('http://catalystframework.org', 'Catalyst') %>
+      <%= $link->('http://mojolicio.us', 'Mojolicious') %>
+      <%= $link->('http://catalystframework.org', 'Catalyst') %>
     </body>
   </html>
 
@@ -559,7 +558,9 @@ Prefixing multiple routes is another good use for C<under>.
 
 =head2 Conditions
 
-Conditions such as C<agent> allow even more powerful route constructs.
+Conditions such as C<agent> and C<host> from
+L<Mojolicious::Plugin::HeaderCondition> allow even more powerful route
+constructs.
 
   # /foo
   get '/foo' => (agent => qr/Firefox/) => sub {
@@ -571,6 +572,17 @@ Conditions such as C<agent> allow even more powerful route constructs.
     shift->render(text => 'Dude, you really need to upgrade to Firefox!');
   };
 
+  # /bar
+  get '/bar' => (host => 'mojolicio.us') => sub {
+    shift->render(text => 'Hello Mojolicious!');
+  };
+
+However you might want to disable automatic route caching in case there are
+routes responding to the same path without conditions attached, since those
+would otherwise get precedence once cached.
+
+  app->routes->cache(0);
+
 =head2 Formats
 
 Formats can be automatically detected by looking at file extensions.
@@ -1,66 +0,0 @@
-package Mojolicious::Plugin::AgentCondition;
-use Mojo::Base 'Mojolicious::Plugin';
-
-# "Wow, there's a million aliens! I've never seen something so mind-blowing!
-#  Ooh, a reception table with muffins!"
-sub register {
-  my ($self, $app) = @_;
-
-  # Agent
-  $app->routes->add_condition(
-    agent => sub {
-      my ($r, $c, $captures, $pattern) = @_;
-
-      # Pattern
-      return unless $pattern && ref $pattern eq 'Regexp';
-
-      # Match
-      my $agent = $c->req->headers->user_agent;
-      return 1 if $agent && $agent =~ $pattern;
-
-      # Nothing
-      return;
-    }
-  );
-}
-
-1;
-__END__
-
-=head1 NAME
-
-Mojolicious::Plugin::AgentCondition - Agent Condition Plugin
-
-=head1 SYNOPSIS
-
-  # Mojolicious
-  $self->plugin('agent_condition');
-  $self->routes->route('/:controller/:action')->over(agent => qr/Firefox/);
-
-  # Mojolicious::Lite
-  plugin 'agent_condition';
-  get '/' => (agent => qr/Firefox/) => sub {...};
-
-=head1 DESCRIPTION
-
-L<Mojolicious::Plugin::AgentCondition> is a routes condition for user agent
-based routes.
-This is a core plugin, that means it is always enabled and its code a good
-example for learning to build new plugins.
-
-=head1 METHODS
-
-L<Mojolicious::Plugin::AgentCondition> inherits all methods from
-L<Mojolicious::Plugin> and implements the following new ones.
-
-=head2 C<register>
-
-  $plugin->register;
-
-Register condition in L<Mojolicious> application.
-
-=head1 SEE ALSO
-
-L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicio.us>.
-
-=cut
@@ -0,0 +1,66 @@
+package Mojolicious::Plugin::CallbackCondition;
+use Mojo::Base 'Mojolicious::Plugin';
+
+# "Stop being such a spineless jellyfish!
+#  You know full well I'm more closely related to the sea cucumber.
+#  Not where it counts."
+sub register {
+  my ($self, $app) = @_;
+
+  # "cb" condition
+  $app->routes->add_condition(
+    cb => sub {
+      my ($r, $c, $captures, $cb) = @_;
+      return unless $cb && ref $cb eq 'CODE';
+      $r->$cb($c, $captures);
+    }
+  );
+}
+
+1;
+__END__
+
+=head1 NAME
+
+Mojolicious::Plugin::CallbackCondition - Callback Condition Plugin
+
+=head1 SYNOPSIS
+
+  # Mojolicious
+  $self->plugin('callback_condition');
+  $self->routes->route('/:controller/:action')->over(cb => sub {
+    my ($r, $c, $captures) = @_;
+    ...
+  });
+
+  # Mojolicious::Lite
+  plugin 'callback_condition';
+  get '/' => (cb => sub {
+    my ($r, $c, $captures) = @_;
+    ...
+  }) => sub {...};
+
+=head1 DESCRIPTION
+
+L<Mojolicious::Plugin::CallbackCondition> is a routes condition for
+callbacks.
+This is a core plugin, that means it is always enabled and its code a good
+example for learning to build new plugins.
+Note that this module is EXPERIMENTAL and might change without warning!
+
+=head1 METHODS
+
+L<Mojolicious::Plugin::CallbackCondition> inherits all methods from
+L<Mojolicious::Plugin> and implements the following new ones.
+
+=head2 C<register>
+
+  $plugin->register;
+
+Register condition in L<Mojolicious> application.
+
+=head1 SEE ALSO
+
+L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicio.us>.
+
+=cut
@@ -7,11 +7,8 @@ use Mojo::Base 'Mojolicious::Plugin';
 sub register {
   my ($self, $app, $conf) = @_;
 
-  # Config
-  $conf ||= {};
-
-
   # Got a charset
+  $conf ||= {};
   if (my $charset = $conf->{charset}) {
 
     # Add charset to text/html content type
@@ -17,7 +17,7 @@ sub load {
   my $content = do { local $/; <$handle> };
 
   # Process
-  return $self->parse($content, $file, $conf, $app);
+  $self->parse($content, $file, $conf, $app);
 }
 
 sub parse {
@@ -30,7 +30,7 @@ sub parse {
   die qq/Config file "$file" did not return a hashref.\n/
     unless ref $config && ref $config eq 'HASH';
 
-  return $config;
+  $config;
 }
 
 sub register {
@@ -88,14 +88,14 @@ sub register {
     config => sub {
       my $self = shift;
       return $config unless @_;
-      return $config->{$_[0]};
+      $config->{$_[0]};
     }
   );
 
-  # Default
+  # Add default stash value
   $app->defaults(($conf->{stash_key} || 'config') => $config);
 
-  return $config;
+  $config;
 }
 
 1;
@@ -38,7 +38,7 @@ sub register {
       my $stash = $self->stash;
       $stash->{extends} = shift if @_;
       $self->stash(@_) if @_;
-      return $stash->{extends};
+      $stash->{extends};
     }
   );
 
@@ -66,7 +66,7 @@ sub register {
       $i++;
       goto START unless $i >= @keys;
 
-      return $self->render_partial(layout => $layout, extend => $extends);
+      $self->render_partial(layout => $layout, extend => $extends);
     }
   );
 
@@ -77,7 +77,7 @@ sub register {
       my $stash = $self->stash;
       $stash->{layout} = shift if @_;
       $self->stash(@_) if @_;
-      return $stash->{layout};
+      $stash->{layout};
     }
   );
 
@@ -89,7 +89,6 @@ sub register {
       my $cb = pop;
       return '' unless ref $cb && ref $cb eq 'CODE';
       my $name = shift;
-
       my $args;
       if (ref $name && ref $name eq 'HASH') {
         $args = $name;
@@ -134,7 +133,7 @@ sub register {
       my $stash = $self->stash;
       $stash->{title} = shift if @_;
       $self->stash(@_) if @_;
-      return $stash->{title};
+      $stash->{title};
     }
   );
 
@@ -1,6 +1,7 @@
 package Mojolicious::Plugin::EpRenderer;
 use Mojo::Base 'Mojolicious::Plugin';
 
+use Mojo::Loader;
 use Mojo::Template;
 use Mojo::Util 'md5_sum';
 
@@ -15,6 +16,11 @@ sub register {
   my $name     = $conf->{name}     || 'ep';
   my $template = $conf->{template} || {};
 
+  # Custom sandbox
+  $template->{namespace} =
+    'Mojo::Template::SandBox::' . md5_sum(($ENV{MOJO_EXE} || ref $app) . $$)
+    unless defined $template->{namespace};
+
   # Auto escape by default to prevent XSS attacks
   $template->{auto_escape} = 1 unless defined $template->{auto_escape};
 
@@ -29,8 +35,6 @@ sub register {
       my $list = join ', ', sort keys %{$c->stash};
       my $key = $options->{cache} = md5_sum "$path($list)";
 
-      $c->stash->{layout} ||= undef;
-
       # Cache
       my $cache = $r->cache;
       unless ($cache->get($key)) {
@@ -50,7 +54,7 @@ sub register {
         for my $name (sort keys %{$r->helpers}) {
           next unless $name =~ /^\w+$/;
           $prepend .= "sub $name; *$name = sub { ";
-          $prepend .= "return \$_H->{'$name'}->(\$self, \@_) };";
+          $prepend .= "\$_H->{'$name'}->(\$self, \@_) };";
         }
 
         # Be less relaxed for everything else
@@ -71,7 +75,7 @@ sub register {
       }
 
       # Render with epl
-      return $r->handlers->{epl}->($r, $c, $output, $options);
+      $r->handlers->{epl}->($r, $c, $output, $options);
     }
   );
 
@@ -13,10 +13,10 @@ sub register {
   $app->renderer->add_handler(
     epl => sub {
       my ($r, $c, $output, $options) = @_;
-      my $inline = $options->{inline};
 
       # Template
-      my $path = $r->template_path($options);
+      my $inline = $options->{inline};
+      my $path   = $r->template_path($options);
       $path = md5_sum $inline if defined $inline;
       return unless defined $path;
 
@@ -25,9 +25,8 @@ sub register {
       my $key   = delete $options->{cache} || $path;
       my $mt    = $cache->get($key);
 
-      $mt ||= Mojo::Template->new;
-
       # Cached
+      $mt ||= Mojo::Template->new;
       if ($mt->compiled) { $$output = $mt->interpret($c) }
 
       # Not cached
@@ -79,7 +78,7 @@ sub register {
       }
 
       # Success or exception
-      return ref $$output ? 0 : 1;
+      ref $$output ? 0 : 1;
     }
   );
 }
@@ -7,35 +7,32 @@ use Mojo::Base 'Mojolicious::Plugin';
 sub register {
   my ($self, $app) = @_;
 
-  # Header
+  # "headers" condition
+  $app->routes->add_condition(headers => \&_headers);
+
+  # "agent" condition
+  $app->routes->add_condition(
+    agent => sub { _headers(@_[0 .. 2], {'User-Agent' => $_[3]}) });
+
+  # "host" condition
   $app->routes->add_condition(
-    headers => sub {
-      my ($r, $c, $captures, $patterns) = @_;
-
-      # Patterns
-      return unless $patterns && ref $patterns eq 'HASH';
-
-      # Match
-      my $passed;
-      while (my ($k, $v) = each(%$patterns)) {
-        my $header = $c->req->headers->header($k);
-        if ($header && $v && ref $v eq 'Regexp' && $header =~ $v) {
-          $passed = 1;
-          next;
-        }
-        elsif ($header && defined $v && $v eq $header) {
-          $passed = 1;
-          next;
-        }
-        $passed = undef;
-      }
-
-      # Success
-      return 1 if $passed;
-
-      return;
-    }
-  );
+    host => sub { _headers(@_[0 .. 2], {'Host' => $_[3]}) });
+}
+
+# "Wow, there's a million aliens! I've never seen something so mind-blowing!
+#  Ooh, a reception table with muffins!"
+sub _headers {
+  my ($r, $c, $captures, $patterns) = @_;
+  return unless $patterns && ref $patterns eq 'HASH' && keys %$patterns;
+
+  # All headers need to match
+  while (my ($k, $v) = each %$patterns) {
+    my $header = $c->req->headers->header($k);
+    if ($header && $v && ref $v eq 'Regexp' && $header =~ $v) {next}
+    elsif ($header && defined $v && $v eq $header) {next}
+    else                                           {return}
+  }
+  return 1;
 }
 
 1;
@@ -49,22 +46,31 @@ Mojolicious::Plugin::HeaderCondition - Header Condition Plugin
 
   # Mojolicious
   $self->plugin('header_condition');
-
-  # Must match all of these headers
-  $self->routes->route('/:controller/:action')->over(headers => {
-    X-Secret-Header => 'Foo',
-    Referer => qr/^https?:\/\/example\.com\//
-  })->to('foo#bar');
+  $self->routes->route('/:controller/:action')
+    ->over(headers => {Referer => qr/example\.com/});
 
   # Mojolicious::Lite
   plugin 'header_condition';
-  get '/' => (headers => {'Referer' => qr/^https?:\/\/example\.com\//})
-    => sub {...};
+  get '/' => (headers => {Referer => qr/example\.com/}) => sub {...};
+
+  # All headers need to match
+  $self->routes->route('/:controller/:action')->over(headers => {
+    'X-Secret-Header' => 'Foo',
+    Referer => qr/example\.com/
+  });
+
+  # The "agent" condition is a shortcut for the "User-Agent" header
+  get '/' => (agent => qr/Firefox/) => sub {...};
+
+  # The "host" condition is a shortcut for the "Host" header
+  get '/' => (host => qr/mojolicio\.us/) => sub {...};
 
 =head1 DESCRIPTION
 
 L<Mojolicious::Plugin::HeaderCondition> is a routes condition for header
 based routes.
+This is a core plugin, that means it is always enabled and its code a good
+example for learning to build new plugins.
 
 =head1 METHODS
 
@@ -8,12 +8,11 @@ use I18N::LangTags::Detect;
 #  No, the cat shelter’s onto me."
 sub register {
   my ($self, $app, $conf) = @_;
-
   $conf ||= {};
-  my $namespace = $conf->{namespace} || ((ref $app) . "::I18N");
-  my $default   = $conf->{default}   || 'en';
 
   # Initialize
+  my $namespace = $conf->{namespace} || ((ref $app) . "::I18N");
+  my $default   = $conf->{default}   || 'en';
   eval "package $namespace; use base 'Locale::Maketext'; 1;";
   eval "require ${namespace}::${default};";
   unless (eval "\%${namespace}::${default}::Lexicon") {
@@ -50,14 +49,12 @@ sub register {
   $app->helper(l => sub { shift->stash->{i18n}->localize(@_) });
 }
 
-# Container
 package Mojolicious::Plugin::I18n::_Handler;
 use Mojo::Base -base;
 
 # "Robot 1-X, save my friends! And Zoidberg!"
 sub languages {
   my ($self, @languages) = @_;
-
   return $self->{_language} unless @languages;
 
   # Handle
@@ -68,16 +65,14 @@ sub languages {
     $self->{_language} = $handle->language_tag;
   }
 
-  return $self;
+  $self;
 }
 
 sub localize {
   my $self = shift;
   my $key  = shift;
-
-  # Localize
   return $key unless my $handle = $self->{_handle};
-  return $handle->maketext($key, @_);
+  $handle->maketext($key, @_);
 }
 
 1;
@@ -19,7 +19,7 @@ sub parse {
   die qq/Couldn't parse config "$file": $error/ if !$config && $error;
   die qq/Invalid config "$file"./ if !$config || ref $config ne 'HASH';
 
-  return $config;
+  $config;
 }
 
 sub register {
@@ -49,7 +49,7 @@ sub render {
   $content = $mt->render($content, $app);
   utf8::encode $content;
 
-  return $content;
+  $content;
 }
 
 1;
@@ -0,0 +1,80 @@
+package Mojolicious::Plugin::Mount;
+use Mojo::Base 'Mojolicious::Plugin';
+
+use Mojo::Server;
+
+sub register {
+  my ($self, $app, $conf) = @_;
+
+  # Extract host and path
+  my $prefix = (keys %$conf)[0];
+  my ($host, $path);
+  if ($prefix =~ /^(\*\.)?([^\/]+)(\/.*)?$/) {
+    $host = quotemeta $2;
+    $host = "(?:.*\\.)?$host" if $1;
+    $path = $3;
+    $path = '/' unless defined $path;
+    $host = qr/^$host$/i;
+    $app->routes->cache(0);
+  }
+  else { $path = $prefix }
+
+  # Generate route
+  my $route =
+    $app->routes->route($path)
+    ->detour(app => Mojo::Server->new->load_app($conf->{$prefix}));
+  $route->over(host => $host) if $host;
+
+  $route;
+}
+
+1;
+__END__
+
+=head1 NAME
+
+Mojolicious::Plugin::Mount - Application Mount Plugin
+
+=head1 SYNOPSIS
+
+  # Mojolicious
+  $self->plugin(mount => {'/prefix' => '/home/sri/myapp.pl'});
+
+  # Mojolicious::Lite
+  plugin mount => {'/prefix' => '/home/sri/myapp.pl'};
+
+  # Adjust the generated route
+  my $example = plugin mount => {'/example' => '/home/sri/example.pl'};
+  $example->to(message => 'It works great!');
+
+  # Mount application with host (automatically disables route caching)
+  plugin mount => {'mojolicio.us' => '/home/sri/myapp.pl'};
+
+  # Host and path
+  plugin mount => {'mojolicio.us/myapp' => '/home/sri/myapp.pl'};
+
+  # Or even hosts with wildcard subdomains
+  plugin mount => {'*.mojolicio.us/myapp' => '/home/sri/myapp.pl'};
+
+=head1 DESCRIPTION
+
+L<Mojolicious::Plugin::Mount> is a plugin that allows you to mount whole
+L<Mojolicious> applications.
+Note that this module is EXPERIMENTAL and might change without warning!
+
+=head1 METHODS
+
+L<Mojolicious::Plugin::Mount> inherits all methods from
+L<Mojolicious::Plugin> and implements the following new ones.
+
+=head2 C<register>
+
+  $plugin->register;
+
+Mount L<Mojolicious> application.
+
+=head1 SEE ALSO
+
+L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicio.us>.
+
+=cut
@@ -114,10 +114,10 @@ sub register {
           url_escape $anchor, 'A-Za-z0-9_';
           $anchor =~ s/\%//g;
           push @$sections, [] if $tag->type eq 'h1' || !@$sections;
-          push @{$sections->[-1]}, $text, "/$url#$anchor";
+          push @{$sections->[-1]}, $text, $url->fragment($anchor)->to_abs;
           $tag->replace_content(
             $self->link_to(
-              $text => "/$url#toc",
+              $text => $url->fragment('toc')->to_abs,
               class => 'mojoscroll',
               id    => $anchor
             )
@@ -160,14 +160,14 @@ sub _pod_to_html {
   # Parse
   my $output;
   $parser->output_string(\$output);
-  eval { $parser->parse_string_document($pod) };
+  eval { $parser->parse_string_document("$pod") };
   return $@ if $@;
 
   # Filter
   $output =~ s/<a name='___top' class='dummyTopAnchor'\s*?><\/a>\n//g;
   $output =~ s/<a class='u'.*?name=".*?"\s*>(.*?)<\/a>/$1/sg;
 
-  return $output;
+  $output;
 }
 
 1;
@@ -13,16 +13,14 @@ sub register {
     after_static_dispatch => sub {
       my $self = shift;
 
-      # New request
-      my $stash  = $self->stash;
+      # Ignore static files
+      my $stash = $self->stash;
+      return if $stash->{'mojo.static'} || $stash->{'mojo.started'};
       my $req    = $self->req;
       my $method = $req->method;
       my $path   = $req->url->path->to_abs_string;
       my $ua     = $req->headers->user_agent || 'Anonymojo';
-      $self->app->log->debug("$method $path ($ua).")
-        unless $stash->{'mojo.static'};
-
-      # Start
+      $self->app->log->debug("$method $path ($ua).");
       $stash->{'mojo.started'} = [Time::HiRes::gettimeofday()];
     }
   );
@@ -32,17 +30,17 @@ sub register {
     after_dispatch => sub {
       my $self = shift;
 
-      # Time
+      # Ignore static files
       my $stash = $self->stash;
-      return unless my $started = $stash->{'mojo.started'};
+      return unless my $started = delete $stash->{'mojo.started'};
+      return if $stash->{'mojo.static'};
       my $elapsed = sprintf '%f',
         Time::HiRes::tv_interval($started, [Time::HiRes::gettimeofday()]);
       my $rps     = $elapsed == 0 ? '??' : sprintf '%.3f', 1 / $elapsed;
       my $res     = $self->res;
       my $code    = $res->code || 200;
       my $message = $res->message || $res->default_message($code);
-      $self->app->log->debug("$code $message (${elapsed}s, $rps/s).")
-        unless $stash->{'mojo.static'};
+      $self->app->log->debug("$code $message (${elapsed}s, $rps/s).");
     }
   );
 }
@@ -1,6 +1,7 @@
 package Mojolicious::Plugin::TagHelpers;
 use Mojo::Base 'Mojolicious::Plugin';
 
+use List::Util 'first';
 use Mojo::ByteStream 'b';
 use Mojo::Util 'xml_escape';
 
@@ -182,7 +183,7 @@ sub register {
             else { $parts .= $cb->($o) }
           }
 
-          return $parts;
+          $parts;
         }
       );
     }
@@ -272,25 +273,22 @@ sub _input {
   else { %attrs = @_ }
 
   # Value
-  my $p = $c->param($name);
+  my @p = $c->param($name);
 
+  # Special selection value
   my $t = $attrs{type} || '';
-  if (defined $p && $t ne 'submit') {
+  if (@p && $t ne 'submit') {
 
-    # Checkbox
-    if ($t eq 'checkbox') {
-      $attrs{checked} = 'checked';
-    }
-
-    # Radiobutton
-    elsif ($t eq 'radio') {
-      my $value = $attrs{value};
-      $value = '' unless defined $value;
-      $attrs{checked} = 'checked' if $value eq $p;
+    # Checkbox or radiobutton
+    my $value = $attrs{value};
+    $value = '' unless defined $value;
+    if ($t eq 'checkbox' || $t eq 'radio') {
+      $attrs{value} = $value;
+      $attrs{checked} = 'checked' if defined first { $value eq $_ } @p;
     }
 
     # Other
-    else { $attrs{value} = $p }
+    else { $attrs{value} = $p[0] }
 
     return $self->_tag('input', name => $name, %attrs);
   }
@@ -331,7 +329,7 @@ sub _tag {
   else { $tag .= ' />' }
 
   # Prevent escaping
-  return b($tag);
+  b($tag);
 }
 
 1;
@@ -596,6 +594,15 @@ HTML5 tag generator.
   <div id="foo" />
   <div>Content</div>
 
+Very useful for reuse in more specific tag helpers.
+
+  $self->tag('div');
+  $self->tag('div', id => 'foo');
+  $self->tag(div => sub { 'Content' });
+
+Results are automatically wrapped in L<Mojo::ByteStream> objects to prevent
+accidental double escaping.
+
 =head2 C<text_field>
 
   <%= text_field 'first_name' %>
@@ -13,7 +13,7 @@ sub add_hook {
   return $self unless $name && $cb;
   $self->hooks->{$name} ||= [];
   push @{$self->hooks->{$name}}, $cb;
-  return $self;
+  $self;
 }
 
 # "Also you have a rectangular object in your colon.
@@ -33,11 +33,7 @@ sub load_plugin {
 
     # Try all namspaces
     for my $namespace (@{$self->namespaces}) {
-
-      # Module
       my $module = "${namespace}::$class";
-
-      # Load and register
       return $module->new if $self->_load($module);
     }
   }
@@ -51,7 +47,7 @@ sub register_plugin {
   my $self = shift;
   my $name = shift;
   my $app  = shift;
-  return $self->load_plugin($name)->register($app, ref $_[0] ? $_[0] : {@_});
+  $self->load_plugin($name)->register($app, ref $_[0] ? $_[0] : {@_});
 }
 
 sub run_hook {
@@ -59,7 +55,7 @@ sub run_hook {
   return $self unless my $name  = shift;
   return $self unless my $hooks = $self->hooks->{$name};
   for my $hook (@$hooks) { $hook->(@_) }
-  return $self;
+  $self;
 }
 
 # "Everybody's a jerk. You, me, this jerk."
@@ -68,20 +64,21 @@ sub run_hook_reverse {
   return $self unless my $name  = shift;
   return $self unless my $hooks = $self->hooks->{$name};
   for my $hook (reverse @$hooks) { $hook->(@_) }
-  return $self;
+  $self;
 }
 
 sub _load {
   my ($self, $module) = @_;
 
   # Load
-  my $e = Mojo::Loader->load($module);
-  if (ref $e) { die $e }
-  return if $e;
+  if (my $e = Mojo::Loader->load($module)) {
+    die $e if ref $e;
+    return;
+  }
 
   # Module is a plugin
   return unless $module->can('new') && $module->can('register');
-  return 1;
+  1;
 }
 
 1;
@@ -49,19 +49,19 @@ sub new {
     }
   );
 
-  return $self;
+  $self;
 }
 
 sub add_handler {
   my ($self, $name, $cb) = @_;
   $self->handlers->{$name} = $cb;
-  return $self;
+  $self;
 }
 
 sub add_helper {
   my ($self, $name, $cb) = @_;
   $self->helpers->{$name} = $cb;
-  return $self;
+  $self;
 }
 
 sub get_data_template {
@@ -75,17 +75,16 @@ sub render {
   my ($self, $c, $args) = @_;
   $args ||= {};
 
-  my $stash = $c->stash;
-  my $content = $stash->{'mojo.content'} ||= {};
-
   # Localize extends and layout
   my $partial = $args->{partial};
+  my $stash   = $c->stash;
   local $stash->{layout}  = $partial ? undef : $stash->{layout};
   local $stash->{extends} = $partial ? undef : $stash->{extends};
 
   # Merge stash and arguments
   while (my ($key, $value) = each %$args) { $stash->{$key} = $value }
 
+  # Extract important stash values
   my $template = delete $stash->{template};
   my $class    = $stash->{template_class};
   my $format   = $stash->{format} || $self->default_format;
@@ -94,6 +93,8 @@ sub render {
   my $json     = delete $stash->{json};
   my $text     = delete $stash->{text};
   my $inline   = delete $stash->{inline};
+
+  # Pick handler
   $handler = $self->default_handler if defined $inline && !defined $handler;
   my $options = {
     template       => $template,
@@ -103,9 +104,10 @@ sub render {
     inline         => $inline,
     template_class => $class
   };
-  my $output;
 
   # Text
+  my $output;
+  my $content = $stash->{'mojo.content'} ||= {};
   if (defined $text) {
     $self->handlers->{text}->($self, $c, \$output, {text => $text});
     $content->{content} = b("$output")
@@ -154,7 +156,7 @@ sub render {
     encode $encoding, $output if $encoding && $output && !$json && !$data;
   }
 
-  return ($output, $c->app->types->type($format) || 'text/plain');
+  ($output, $c->app->types->type($format) || 'text/plain');
 }
 
 sub template_name {
@@ -162,18 +164,17 @@ sub template_name {
 
   return unless my $template = $options->{template} || '';
   return unless my $format = $options->{format};
-
   my $handler = $options->{handler};
   my $file    = "$template.$format";
   $file = "$file.$handler" if defined $handler;
 
-  return $file;
+  $file;
 }
 
 sub template_path {
   my $self = shift;
   return unless my $name = $self->template_name(shift);
-  return File::Spec->catfile($self->root, split '/', $name);
+  File::Spec->catfile($self->root, split '/', $name);
 }
 
 sub _detect_handler {
@@ -201,14 +202,13 @@ sub _detect_handler {
     if ($template =~ /^$file\.(\w+)$/) { return $1 }
   }
 
-  return;
+  undef;
 }
 
 # "You are hereby conquered.
 #  Please line up in order of how much beryllium it takes to kill you."
 sub _detect_template_class {
   my ($self, $options) = @_;
-  return
        $options->{template_class}
     || $ENV{MOJO_TEMPLATE_CLASS}
     || $self->default_template_class
@@ -221,13 +221,13 @@ sub _extends {
   if (my $layout = delete $stash->{layout}) {
     $stash->{extends} ||= $self->layout_prefix . '/' . $layout;
   }
-  return delete $stash->{extends};
+  delete $stash->{extends};
 }
 
 sub _list_data_templates {
   my ($self, $class) = @_;
   my $all = Mojo::Command->new->get_all_data($class);
-  return [keys %$all];
+  [keys %$all];
 }
 
 # "Well, at least here you'll be treated with dignity.
@@ -253,7 +253,7 @@ sub _render_template {
   return unless $renderer->($self, $c, $output, $options);
 
   # Success!
-  return 1;
+  1;
 }
 
 1;
@@ -25,7 +25,7 @@ sub new {
   # WebSocket
   $self->{_websocket} = shift;
 
-  return $self;
+  $self;
 }
 
 # "Life can be hilariously cruel."
@@ -33,16 +33,12 @@ sub match {
   my ($self, $r, $c) = @_;
   return unless $r;
 
-  my $dictionary = $self->{_dictionary} ||= $r->dictionary;
-
-  # Root
-  $self->root($r) unless $self->root;
-
-  my $path    = $self->{_path};
-  my $pattern = $r->pattern;
-
   # Match
-  my $captures = $pattern->shape_match(\$path);
+  $self->root($r) unless $self->root;
+  my $dictionary = $self->{_dictionary} ||= $r->dictionary;
+  my $path       = $self->{_path};
+  my $pattern    = $r->pattern;
+  my $captures   = $pattern->shape_match(\$path);
   return unless $captures;
   $self->{_path} = $path;
 
@@ -80,8 +76,8 @@ sub match {
   my $empty = !length $path || $path eq '/' ? 1 : 0;
 
   # Partial
-  if (my $partial = $r->partial) {
-    $captures->{$partial} = $path;
+  if ($r->partial) {
+    $captures->{path} = $path;
     $self->endpoint($r);
     $empty = 1;
   }
@@ -113,8 +109,6 @@ sub match {
   # Match children
   my $snapshot = [@{$self->stack}];
   for my $child (@{$r->children}) {
-
-    # Match
     $self->match($child, $c);
 
     # Endpoint found
@@ -131,7 +125,7 @@ sub match {
     }
   }
 
-  return $self;
+  $self;
 }
 
 sub path_for {
@@ -210,7 +204,7 @@ sub path_for {
   # Render
   my $path = $endpoint->render('', $values);
   utf8::downgrade $path, 1;
-  return wantarray ? ($path, $endpoint->has_websocket) : $path;
+  wantarray ? ($path, $endpoint->has_websocket) : $path;
 }
 
 1;
@@ -16,20 +16,14 @@ has [qw/format pattern regex/];
 sub new {
   my $self = shift->SUPER::new();
   $self->parse(@_);
-  return $self;
+  $self;
 }
 
 sub match {
   my ($self, $path) = @_;
-
-  # Match
   my $result = $self->shape_match(\$path);
-
-  # Endpoint
   return $result if !$path || $path eq '/';
-
-  # Partial or no match
-  return;
+  undef;
 }
 
 sub parse {
@@ -51,7 +45,7 @@ sub parse {
   $self->pattern($pattern);
   $self->_tokenize;
 
-  return $self;
+  $self;
 }
 
 sub render {
@@ -61,6 +55,7 @@ sub render {
   $values ||= {};
   $values = {%{$self->defaults}, %$values};
 
+  # Turn pattern into path
   my $string   = '';
   my $optional = 1;
   for my $token (reverse @{$self->tree}) {
@@ -83,10 +78,8 @@ sub render {
       my $name = $token->[1];
       $rendered = $values->{$name};
       $rendered = '' unless defined $rendered;
-
       my $default = $self->defaults->{$name};
       $default = '' unless defined $default;
-
       $optional = 0 unless $default eq $rendered;
       $rendered = '' if $optional && $default eq $rendered;
     }
@@ -94,7 +87,7 @@ sub render {
     $string = "$rendered$string";
   }
 
-  return $string || '/';
+  $string || '/';
 }
 
 sub shape_match {
@@ -120,12 +113,13 @@ sub shape_match {
     return $result;
   }
 
-  return;
+  undef;
 }
 
 sub _compile {
   my $self = shift;
 
+  # Compile tree to regular expression
   my $block    = '';
   my $regex    = '';
   my $optional = 1;
@@ -154,7 +148,6 @@ sub _compile {
     # Symbol
     elsif ($op eq 'relaxed' || $op eq 'symbol' || $op eq 'wildcard') {
       my $name = $token->[1];
-
       unshift @{$self->symbols}, $name;
 
       # Relaxed
@@ -166,11 +159,12 @@ sub _compile {
       # Wildcard
       elsif ($op eq 'wildcard') { $compiled = '(.+)' }
 
+      # Custom regex
       my $req = $self->reqs->{$name};
       $compiled = "($req)" if $req;
 
+      # Optional placeholder
       $optional = 0 unless exists $self->defaults->{$name};
-
       $compiled .= '?' if $optional;
     }
 
@@ -184,22 +178,24 @@ sub _compile {
   $regex = qr/^$regex/;
   $self->regex($regex);
 
-  return $regex;
+  $regex;
 }
 
 sub _tokenize {
   my $self = shift;
 
-  my $pattern        = $self->pattern;
+  # Token
   my $quote_end      = $self->quote_end;
   my $quote_start    = $self->quote_start;
   my $relaxed_start  = $self->relaxed_start;
   my $symbol_start   = $self->symbol_start;
   my $wildcard_start = $self->wildcard_start;
-  my $tree           = [];
-  my $state          = 'text';
-  my $quoted         = 0;
 
+  # Parse the pattern character wise
+  my $pattern = $self->pattern;
+  my $tree    = [];
+  my $state   = 'text';
+  my $quoted  = 0;
   while (length(my $char = substr $pattern, 0, 1, '')) {
 
     # Inside a symbol
@@ -261,7 +257,6 @@ sub _tokenize {
 
     # Text
     else {
-
       $state = 'text';
 
       # New text element
@@ -276,7 +271,7 @@ sub _tokenize {
   }
   $self->tree($tree);
 
-  return $self;
+  $self;
 }
 
 1;
@@ -28,7 +28,7 @@ sub AUTOLOAD {
   # Call shortcut
   Carp::croak(qq/Can't locate object method "$method" via package "$package"/)
     unless my $shortcut = $self->shortcuts->{$method};
-  return $self->$shortcut(@_);
+  $self->$shortcut(@_);
 }
 
 sub DESTROY { }
@@ -36,7 +36,7 @@ sub DESTROY { }
 sub new {
   my $self = shift->SUPER::new();
   $self->parse(@_);
-  return $self;
+  $self;
 }
 
 sub add_child {
@@ -46,25 +46,25 @@ sub add_child {
   $route->parent($self);
   weaken $route->{parent};
 
-  # Shortcuts
+  # Inherit shortcuts
   $route->shortcuts($self->shortcuts);
 
   # Add to tree
   push @{$self->children}, $route;
 
-  return $self;
+  $self;
 }
 
 sub add_condition {
   my ($self, $name, $cb) = @_;
   $self->dictionary->{$name} = $cb;
-  return $self;
+  $self;
 }
 
 sub add_shortcut {
   my ($self, $name, $cb) = @_;
   $self->shortcuts->{$name} = $cb;
-  return $self;
+  $self;
 }
 
 sub any {
@@ -88,7 +88,7 @@ sub auto_render {
     1;
   } or $c->render_exception($@);
 
-  return;
+  1;
 }
 
 sub bridge { shift->route(@_)->inline(1) }
@@ -97,9 +97,9 @@ sub del { shift->_generate_route('delete', @_) }
 
 sub detour {
   my $self = shift;
-  $self->partial('path');
+  $self->partial(1);
   $self->to(@_);
-  return $self;
+  $self;
 }
 
 sub dispatch {
@@ -119,7 +119,7 @@ sub dispatch {
 
   # Cached
   my $cache = $self->cache;
-  if (my $cached = $cache->get("$method:$path:$websocket")) {
+  if ($cache && (my $cached = $cache->get("$method:$path:$websocket"))) {
     $m->root($self);
     $m->stack($cached->{stack});
     $m->captures($cached->{captures});
@@ -131,7 +131,7 @@ sub dispatch {
     $m->match($self, $c);
 
     # Endpoint found
-    if (my $endpoint = $m->endpoint) {
+    if ($cache && (my $endpoint = $m->endpoint)) {
 
       # Cache routes without conditions
       $cache->set(
@@ -145,13 +145,13 @@ sub dispatch {
   }
 
   # No match
-  return 1 unless $m && @{$m->stack};
+  return unless $m && @{$m->stack};
 
   # Walk the stack
-  return 1 if $self->_walk_stack($c);
+  return if $self->_walk_stack($c);
 
   # Render
-  return $self->auto_render($c);
+  $self->auto_render($c);
 }
 
 sub get { shift->_generate_route('get', @_) }
@@ -160,19 +160,19 @@ sub has_conditions {
   my $self = shift;
   return 1 if @{$self->conditions};
   if (my $parent = $self->parent) { return $parent->has_conditions }
-  return;
+  undef;
 }
 
 sub has_custom_name {
   return 1 if shift->{_custom};
-  return;
+  undef;
 }
 
 sub has_websocket {
   my $self = shift;
   return 1 if $self->is_websocket;
   if (my $parent = $self->parent) { return $parent->is_websocket }
-  return;
+  undef;
 }
 
 sub hide { push @{shift->hidden}, @_ }
@@ -182,12 +182,12 @@ sub is_endpoint {
   return   if $self->inline;
   return 1 if $self->block;
   return   if @{$self->children};
-  return 1;
+  1;
 }
 
 sub is_websocket {
   return 1 if shift->{_websocket};
-  return;
+  undef;
 }
 
 sub name {
@@ -204,7 +204,7 @@ sub name {
   elsif (@_) { return $self }
 
   # Name
-  return $self->{_name};
+  $self->{_name};
 }
 
 sub over {
@@ -212,7 +212,7 @@ sub over {
   return $self unless @_;
   my $conditions = ref $_[0] eq 'ARRAY' ? $_[0] : [@_];
   push @{$self->conditions}, @$conditions;
-  return $self;
+  $self;
 }
 
 sub parse {
@@ -228,7 +228,7 @@ sub parse {
   $self->{_name}   = $name;
   $self->{_custom} = 0;
 
-  return $self;
+  $self;
 }
 
 sub post { shift->_generate_route('post', @_) }
@@ -253,16 +253,14 @@ sub render {
   # Parent
   $path = $self->parent->render($path, $values) if $self->parent;
 
-  return $path;
+  $path;
 }
 
-# "Morbo forget how you spell that letter that looks like a man wearing a hat.
-#  Hello, tiny man. I will destroy you!"
 sub route {
   my $self  = shift;
   my $route = $self->new(@_);
   $self->add_child($route);
-  return $route;
+  $route;
 }
 
 sub to {
@@ -316,21 +314,19 @@ sub to {
     }
   }
 
-  # Pattern
-  my $pattern = $self->pattern;
-
   # Defaults
-  my $old = $pattern->defaults;
+  my $pattern = $self->pattern;
+  my $old     = $pattern->defaults;
   $pattern->defaults({%$old, %$defaults}) if $defaults;
 
-  return $self;
+  $self;
 }
 
 sub to_string {
   my $self = shift;
   my $pattern = $self->parent ? $self->parent->to_string : '';
   $pattern .= $self->pattern->pattern if $self->pattern->pattern;
-  return $pattern;
+  $pattern;
 }
 
 sub under { shift->_generate_route('under', @_) }
@@ -346,7 +342,7 @@ sub via {
   }
 
   # Get
-  return $self->{_via};
+  $self->{_via};
 }
 
 sub waypoint { shift->route(@_)->block(1) }
@@ -355,7 +351,7 @@ sub websocket {
   my $self  = shift;
   my $route = $self->any(@_);
   $route->{_websocket} = 1;
-  return $route;
+  $route;
 }
 
 sub _dispatch_callback {
@@ -374,7 +370,7 @@ sub _dispatch_callback {
   }
 
   return 1 if !$staging || $continue;
-  return;
+  undef;
 }
 
 sub _dispatch_controller {
@@ -384,10 +380,9 @@ sub _dispatch_controller {
   return 1
     unless my $app = $field->{app} || $self->_generate_class($field, $c);
   my $method = $self->_generate_method($field, $c);
-
   my $dispatch = ref $app || $app;
   $dispatch .= "->$method" if $method;
-  $c->app->log->debug("Dispatching $dispatch.");
+  $c->app->log->debug(qq/Dispatching "$dispatch"./);
 
   # Load class
   if (!ref $app && !$self->{_loaded}->{$app}) {
@@ -424,7 +419,12 @@ sub _dispatch_controller {
       }
 
       # Render
-      elsif (!$staging) { $self->auto_render($app) }
+      else {
+        $c->app->log->debug(
+          qq/Action "$dispatch" not found, assuming template without action./
+        );
+        $self->auto_render($app) unless $staging;
+      }
 
       # Merge stash
       my $new = $app->stash;
@@ -458,7 +458,7 @@ sub _dispatch_controller {
   }
 
   return 1 if !$staging || $continue;
-  return;
+  undef;
 }
 
 sub _generate_class {
@@ -482,7 +482,7 @@ sub _generate_class {
   # Invalid
   return unless $class =~ /^[a-zA-Z0-9_:]+$/;
 
-  return $class;
+  $class;
 }
 
 sub _generate_method {
@@ -494,9 +494,8 @@ sub _generate_method {
     $self->{_hidden}->{$_}++ for @{$self->hidden};
   }
 
-  return unless my $method = $field->{method} || $field->{action};
-
   # Hidden
+  return unless my $method = $field->{method} || $field->{action};
   if ($self->{_hidden}->{$method} || index($method, '_') == 0) {
     $c->app->log->debug(qq/Action "$method" is not allowed./);
     return;
@@ -508,16 +507,15 @@ sub _generate_method {
     return;
   }
 
-  return $method;
+  $method;
 }
 
 sub _generate_route {
   my ($self, $methods, @args) = @_;
 
+  # Route information
   my ($cb, $constraints, $defaults, $name, $pattern);
   my $conditions = [];
-
-  # Route information
   while (defined(my $arg = shift @args)) {
 
     # First scalar is the pattern
@@ -543,9 +541,7 @@ sub _generate_route {
 
   # Defaults
   $constraints ||= [];
-
-  # Defaults
-  $defaults ||= {};
+  $defaults    ||= {};
   $defaults->{cb} = $cb if $cb;
 
   # Create bridge
@@ -558,7 +554,7 @@ sub _generate_route {
     $self->route($pattern, {@$constraints})->over($conditions)->via($methods)
     ->to($defaults)->name($name);
 
-  return $route;
+  $route;
 }
 
 sub _walk_stack {
@@ -568,12 +564,11 @@ sub _walk_stack {
   local $SIG{__DIE__} =
     sub { ref $_[0] ? CORE::die($_[0]) : Mojo::Exception->throw(@_) };
 
-  my $stack = $c->match->stack;
-  my $stash = $c->stash;
-  $stash->{'mojo.captures'} ||= {};
-
   # Walk the stack
+  my $stack   = $c->match->stack;
+  my $stash   = $c->stash;
   my $staging = @$stack;
+  $stash->{'mojo.captures'} ||= {};
   for my $field (@$stack) {
     $staging--;
 
@@ -601,7 +596,7 @@ sub _walk_stack {
   }
 
   # Done
-  return;
+  undef;
 }
 
 1;
@@ -685,6 +680,10 @@ The children of this routes object, used for nesting routes.
 Routing cache, by default a L<Mojo::Cache> object.
 Note that this attribute is EXPERIMENTAL and might change without warning!
 
+  $r->cache(0);
+
+Route caching can also be disabled with a false value.
+
 =head2 C<conditions>
 
   my $conditions  = $r->conditions;
@@ -738,10 +737,9 @@ The parent of this route, used for nesting routes.
 =head2 C<partial>
 
   my $partial = $r->partial;
-  $r          = $r->partial('path');
+  $r          = $r->partial(1);
 
-Route has no specific end, remaining characters will be captured with the
-partial name.
+Route has no specific end, remaining characters will be captured in C<path>.
 
 =head2 C<pattern>
 
@@ -835,7 +833,7 @@ application embedding.
 
 =head2 C<dispatch>
 
-  my $e = $r->dispatch(Mojolicious::Controller->new);
+  my $success = $r->dispatch(Mojolicious::Controller->new);
 
 Match routes and dispatch.
 
@@ -20,11 +20,9 @@ sub load {
   # Session cookie
   return unless my $value = $c->signed_cookie($self->cookie_name);
 
-  # Decode
+  # Deserialize
   $value =~ s/\-/\=/g;
   b64_decode $value;
-
-  # Deserialize
   return unless my $session = $JSON->decode($value);
 
   # Expiration
@@ -69,8 +67,6 @@ sub store {
 
     # Serialize
     $value = $JSON->encode($session);
-
-    # Encode
     b64_encode $value, '';
     $value =~ s/\=/\-/g;
   }
@@ -17,26 +17,29 @@ sub dispatch {
   my ($self, $c) = @_;
 
   # Already rendered
-  return if $c->res->code;
+  return 1 if $c->res->code;
 
   # Canonical path
-  my $path = $c->req->url->path->clone->canonicalize->to_string;
+  my $stash = $c->stash;
+  my $path  = $stash->{path};
+  $path = $c->req->url->path->clone->canonicalize->to_string
+    unless defined $path;
 
   # Split parts
   my @parts = @{Mojo::Path->new->parse($path)->parts};
-  return 1 unless @parts;
+  return unless @parts;
 
   # Prevent directory traversal
-  return 1 if $parts[0] eq '..';
+  return if $parts[0] eq '..';
 
   # Serve static file
-  unless ($self->serve($c, join('/', @parts))) {
-    $c->stash->{'mojo.static'} = 1;
+  if ($self->serve($c, join('/', @parts))) {
+    $stash->{'mojo.static'} = 1;
     $c->rendered;
-    return;
+    return 1;
   }
 
-  return 1;
+  1;
 }
 
 sub serve {
@@ -76,7 +79,7 @@ sub serve {
       # Exists, but is forbidden
       else {
         $c->app->log->debug(qq/File "$rel" forbidden./);
-        $res->code(403) and return;
+        $res->code(403) and return 1;
       }
 
       # Done
@@ -84,8 +87,8 @@ sub serve {
     }
   }
 
-  # Inline file
-  if (!$asset && defined(my $file = $self->_get_inline_file($c, $rel))) {
+  # DATA file
+  if (!$asset && defined(my $file = $self->_get_data_file($c, $rel))) {
     $size  = length $file;
     $asset = Mojo::Asset::Memory->new->add_chunk($file);
   }
@@ -105,7 +108,7 @@ sub serve {
         $rsh->remove('Content-Type');
         $rsh->remove('Content-Length');
         $rsh->remove('Content-Disposition');
-        return;
+        return 1;
       }
     }
 
@@ -126,7 +129,7 @@ sub serve {
 
         # Not satisfiable
         $res->code(416);
-        return;
+        return 1;
       }
     }
     $asset->start_range($start);
@@ -138,35 +141,33 @@ sub serve {
     $rsh->content_type($c->app->types->type($ext) || 'text/plain');
     $rsh->accept_ranges('bytes');
     $rsh->last_modified(Mojo::Date->new($modified));
-    return;
+    return 1;
   }
 
-  return 1;
+  undef;
 }
 
-sub _get_inline_file {
+sub _get_data_file {
   my ($self, $c, $rel) = @_;
 
   # Protect templates
   return if $rel =~ /\.\w+\.\w+$/;
 
-  # Class
+  # Detect DATA class
   my $class =
        $c->stash->{static_class}
     || $ENV{MOJO_STATIC_CLASS}
     || $self->default_static_class
     || 'main';
 
-  # Inline files
-  my $inline = $self->{_inline_files}->{$class}
+  # Find DATA file
+  my $data = $self->{_data_files}->{$class}
     ||= [keys %{Mojo::Command->new->get_all_data($class) || {}}];
-
-  # Find inline file
-  for my $path (@$inline) {
+  for my $path (@$data) {
     return Mojo::Command->new->get_data($path, $class) if $path eq $rel;
   }
 
-  return;
+  undef;
 }
 
 1;
@@ -36,7 +36,7 @@ sub type {
     $self->types->{$ext} = $type;
     return $self;
   }
-  return $self->types->{$ext || ''};
+  $self->types->{$ext || ''};
 }
 
 1;
@@ -1 +1 @@
-.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun{color:#660}.pln{color:#000}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec{color:#606}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}@media print{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun{color:#440}.pln{color:#000}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}
\ No newline at end of file
+.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}
\ No newline at end of file
@@ -1,2 +1,2 @@
-PR.registerLangHandler(PR.createSimpleLexer([["com",/^#[^\r\n]*/,null,"#"],["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/,null,'"']],[["kwd",/^(?:ADS|AD|AUG|BZF|BZMF|CAE|CAF|CA|CCS|COM|CS|DAS|DCA|DCOM|DCS|DDOUBL|DIM|DOUBLE|DTCB|DTCF|DV|DXCH|EDRUPT|EXTEND|INCR|INDEX|NDX|INHINT|LXCH|MASK|MSK|MP|MSU|NOOP|OVSK|QXCH|RAND|READ|RELINT|RESUME|RETURN|ROR|RXOR|SQUARE|SU|TCR|TCAA|OVSK|TCF|TC|TS|WAND|WOR|WRITE|XCH|XLQ|XXALQ|ZL|ZQ|ADD|ADZ|SUB|SUZ|MPY|MPR|MPZ|DVP|COM|ABS|CLA|CLZ|LDQ|STO|STQ|ALS|LLS|LRS|TRA|TSQ|TMI|TOV|AXT|TIX|DLY|INP|OUT)\s/,
-null],["typ",/^(?:-?GENADR|=MINUS|2BCADR|VN|BOF|MM|-?2CADR|-?[1-6]DNADR|ADRES|BBCON|[SE]?BANK\=?|BLOCK|BNKSUM|E?CADR|COUNT\*?|2?DEC\*?|-?DNCHAN|-?DNPTR|EQUALS|ERASE|MEMORY|2?OCT|REMADR|SETLOC|SUBRO|ORG|BSS|BES|SYN|EQU|DEFINE|END)\s/,null],["lit",/^\'(?:-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?)?/],["pln",/^-*(?:[!-z_]|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?/i],["pun",/^[^\w\t\n\r \xA0()\"\\\';]+/]]),["apollo","agc","aea"])
\ No newline at end of file
+PR.registerLangHandler(PR.createSimpleLexer([["com",/^#[^\n\r]*/,null,"#"],["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,null,'"']],[["kwd",/^(?:ADS|AD|AUG|BZF|BZMF|CAE|CAF|CA|CCS|COM|CS|DAS|DCA|DCOM|DCS|DDOUBL|DIM|DOUBLE|DTCB|DTCF|DV|DXCH|EDRUPT|EXTEND|INCR|INDEX|NDX|INHINT|LXCH|MASK|MSK|MP|MSU|NOOP|OVSK|QXCH|RAND|READ|RELINT|RESUME|RETURN|ROR|RXOR|SQUARE|SU|TCR|TCAA|OVSK|TCF|TC|TS|WAND|WOR|WRITE|XCH|XLQ|XXALQ|ZL|ZQ|ADD|ADZ|SUB|SUZ|MPY|MPR|MPZ|DVP|COM|ABS|CLA|CLZ|LDQ|STO|STQ|ALS|LLS|LRS|TRA|TSQ|TMI|TOV|AXT|TIX|DLY|INP|OUT)\s/,
+null],["typ",/^(?:-?GENADR|=MINUS|2BCADR|VN|BOF|MM|-?2CADR|-?[1-6]DNADR|ADRES|BBCON|[ES]?BANK=?|BLOCK|BNKSUM|E?CADR|COUNT\*?|2?DEC\*?|-?DNCHAN|-?DNPTR|EQUALS|ERASE|MEMORY|2?OCT|REMADR|SETLOC|SUBRO|ORG|BSS|BES|SYN|EQU|DEFINE|END)\s/,null],["lit",/^'(?:-*(?:\w|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?)?/],["pln",/^-*(?:[!-z]|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?/],["pun",/^[^\w\t\n\r "'-);\\\xa0]+/]]),["apollo","agc","aea"]);
@@ -0,0 +1,18 @@
+/*
+ Copyright (C) 2011 Google Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+var a=null;
+PR.registerLangHandler(PR.createSimpleLexer([["opn",/^[([{]+/,a,"([{"],["clo",/^[)\]}]+/,a,")]}"],["com",/^;[^\n\r]*/,a,";"],["pln",/^[\t\n\r \xa0]+/,a,"\t\n\r \xa0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,a,'"']],[["kwd",/^(?:def|if|do|let|quote|var|fn|loop|recur|throw|try|monitor-enter|monitor-exit|defmacro|defn|defn-|macroexpand|macroexpand-1|for|doseq|dosync|dotimes|and|or|when|not|assert|doto|proxy|defstruct|first|rest|cons|defprotocol|deftype|defrecord|reify|defmulti|defmethod|meta|with-meta|ns|in-ns|create-ns|import|intern|refer|alias|namespace|resolve|ref|deref|refset|new|set!|memfn|to-array|into-array|aset|gen-class|reduce|map|filter|find|nil?|empty?|hash-map|hash-set|vec|vector|seq|flatten|reverse|assoc|dissoc|list|list?|disj|get|union|difference|intersection|extend|extend-type|extend-protocol|prn)\b/,a],
+["typ",/^:[\dA-Za-z-]+/]]),["clj"]);
@@ -1,2 +1,2 @@
-PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[ \t\r\n\f]+/,null," \t\r\n\u000c"]],[["str",/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],["str",/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],["kwd",/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],
-["com",/^(?:<!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#(?:[0-9a-f]{3}){1,2}/i],["pln",/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],["pun",/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^\)\"\']+/]]),["css-str"])
\ No newline at end of file
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n"]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com",
+/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]);
@@ -0,0 +1 @@
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["pln",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])+(?:'|$)|`[^`]*(?:`|$))/,null,"\"'"]],[["com",/^(?:\/\/[^\n\r]*|\/\*[\S\s]*?\*\/)/],["pln",/^(?:[^"'/`]|\/(?![*/]))+/]]),["go"]);
@@ -1,2 +1,2 @@
-PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\x0B\x0C\r ]+/,null,"\t\n\u000b\u000c\r "],["str",/^\"(?:[^\"\\\n\x0C\r]|\\[\s\S])*(?:\"|$)/,null,'"'],["str",/^\'(?:[^\'\\\n\x0C\r]|\\[^&])\'?/,null,"'"],["lit",/^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+\-]?\d+)?)/i,null,"0123456789"]],[["com",/^(?:(?:--+(?:[^\r\n\x0C]*)?)|(?:\{-(?:[^-]|-+[^-\}])*-\}))/],["kwd",/^(?:case|class|data|default|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|module|newtype|of|then|type|where|_)(?=[^a-zA-Z0-9\']|$)/,
-null],["pln",/^(?:[A-Z][\w\']*\.)*[a-zA-Z][\w\']*/],["pun",/^[^\t\n\x0B\x0C\r a-zA-Z0-9\'\"]+/]]),["hs"])
\ No newline at end of file
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t-\r ]+/,null,"\t\n\r "],["str",/^"(?:[^\n\f\r"\\]|\\[\S\s])*(?:"|$)/,null,'"'],["str",/^'(?:[^\n\f\r'\\]|\\[^&])'?/,null,"'"],["lit",/^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+-]?\d+)?)/i,null,"0123456789"]],[["com",/^(?:--+[^\n\f\r]*|{-(?:[^-]|-+[^}-])*-})/],["kwd",/^(?:case|class|data|default|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|module|newtype|of|then|type|where|_)(?=[^\d'A-Za-z]|$)/,
+null],["pln",/^(?:[A-Z][\w']*\.)*[A-Za-z][\w']*/],["pun",/^[^\d\t-\r "'A-Za-z]+/]]),["hs"]);
@@ -1,2 +1,3 @@
-PR.registerLangHandler(PR.createSimpleLexer([["opn",/^\(/,null,"("],["clo",/^\)/,null,")"],["com",/^;[^\r\n]*/,null,";"],["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/,null,'"']],[["kwd",/^(?:block|c[ad]+r|catch|con[ds]|def(?:ine|un)|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\b/,
-null],["lit",/^[+\-]?(?:0x[0-9a-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[ed][+\-]?\d+)?)/i],["lit",/^\'(?:-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?)?/],["pln",/^-*(?:[a-z_]|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?/i],["pun",/^[^\w\t\n\r \xA0()\"\\\';]+/]]),["cl","el","lisp","scm"])
\ No newline at end of file
+var a=null;
+PR.registerLangHandler(PR.createSimpleLexer([["opn",/^\(+/,a,"("],["clo",/^\)+/,a,")"],["com",/^;[^\n\r]*/,a,";"],["pln",/^[\t\n\r \xa0]+/,a,"\t\n\r \xa0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,a,'"']],[["kwd",/^(?:block|c[ad]+r|catch|con[ds]|def(?:ine|un)|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\b/,a],
+["lit",/^[+-]?(?:[#0]x[\da-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[de][+-]?\d+)?)/i],["lit",/^'(?:-*(?:\w|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?)?/],["pln",/^-*(?:[_a-z]|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?/i],["pun",/^[^\w\t\n\r "'-);\\\xa0]+/]]),["cl","el","lisp","scm"]);
@@ -1,2 +1,2 @@
-PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^(?:\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)|\'(?:[^\'\\]|\\[\s\S])*(?:\'|$))/,null,"\"'"]],[["com",/^--(?:\[(=*)\[[\s\S]*?(?:\]\1\]|$)|[^\r\n]*)/],["str",/^\[(=*)\[[\s\S]*?(?:\]\1\]|$)/],["kwd",/^(?:and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,null],["lit",/^[+-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i],
-["pln",/^[a-z_]\w*/i],["pun",/^[^\w\t\n\r \xA0][^\w\t\n\r \xA0\"\'\-\+=]*/]]),["lua"])
\ No newline at end of file
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["str",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$))/,null,"\"'"]],[["com",/^--(?:\[(=*)\[[\S\s]*?(?:]\1]|$)|[^\n\r]*)/],["str",/^\[(=*)\[[\S\s]*?(?:]\1]|$)/],["kwd",/^(?:and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,null],["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i],
+["pln",/^[_a-z]\w*/i],["pun",/^[^\w\t\n\r \xa0][^\w\t\n\r "'+=\xa0-]*/]]),["lua"]);
@@ -1,2 +1,2 @@
-PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["com",/^#(?:if[\t\n\r \xA0]+(?:[a-z_$][\w\']*|``[^\r\n\t`]*(?:``|$))|else|endif|light)/i,null,"#"],["str",/^(?:\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)|\'(?:[^\'\\]|\\[\s\S])*(?:\'|$))/,null,"\"'"]],[["com",/^(?:\/\/[^\r\n]*|\(\*[\s\S]*?\*\))/],["kwd",/^(?:abstract|and|as|assert|begin|class|default|delegate|do|done|downcast|downto|elif|else|end|exception|extern|false|finally|for|fun|function|if|in|inherit|inline|interface|internal|lazy|let|match|member|module|mutable|namespace|new|null|of|open|or|override|private|public|rec|return|static|struct|then|to|true|try|type|upcast|use|val|void|when|while|with|yield|asr|land|lor|lsl|lsr|lxor|mod|sig|atomic|break|checked|component|const|constraint|constructor|continue|eager|event|external|fixed|functor|global|include|method|mixin|object|parallel|process|protected|pure|sealed|trait|virtual|volatile)\b/],
-["lit",/^[+\-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i],["pln",/^(?:[a-z_]\w*[!?#]?|``[^\r\n\t`]*(?:``|$))/i],["pun",/^[^\t\n\r \xA0\"\'\w]+/]]),["fs","ml"])
\ No newline at end of file
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["com",/^#(?:if[\t\n\r \xa0]+(?:[$_a-z][\w']*|``[^\t\n\r`]*(?:``|$))|else|endif|light)/i,null,"#"],["str",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])(?:'|$))/,null,"\"'"]],[["com",/^(?:\/\/[^\n\r]*|\(\*[\S\s]*?\*\))/],["kwd",/^(?:abstract|and|as|assert|begin|class|default|delegate|do|done|downcast|downto|elif|else|end|exception|extern|false|finally|for|fun|function|if|in|inherit|inline|interface|internal|lazy|let|match|member|module|mutable|namespace|new|null|of|open|or|override|private|public|rec|return|static|struct|then|to|true|try|type|upcast|use|val|void|when|while|with|yield|asr|land|lor|lsl|lsr|lxor|mod|sig|atomic|break|checked|component|const|constraint|constructor|continue|eager|event|external|fixed|functor|global|include|method|mixin|object|parallel|process|protected|pure|sealed|trait|virtual|volatile)\b/],
+["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i],["pln",/^(?:[_a-z][\w']*[!#?]?|``[^\t\n\r`]*(?:``|$))/i],["pun",/^[^\w\t\n\r "'\xa0]+/]]),["fs","ml"]);
@@ -0,0 +1,4 @@
+var a=null;
+PR.registerLangHandler(PR.createSimpleLexer([["str",/^(?:'(?:[^\n\r'\\]|\\.)*'|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,a,'"'],["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,a,"#"],["pln",/^\s+/,a," \r\n\t\xa0"]],[["str",/^@"(?:[^"]|"")*(?:"|$)/,a],["str",/^<#[^#>]*(?:#>|$)/,a],["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,a],["com",/^\/\/[^\n\r]*/,a],["com",/^\/\*[\S\s]*?(?:\*\/|$)/,
+a],["kwd",/^(?:abstract|and|as|base|catch|class|def|delegate|enum|event|extern|false|finally|fun|implements|interface|internal|is|macro|match|matches|module|mutable|namespace|new|null|out|override|params|partial|private|protected|public|ref|sealed|static|struct|syntax|this|throw|true|try|type|typeof|using|variant|virtual|volatile|when|where|with|assert|assert2|async|break|checked|continue|do|else|ensures|for|foreach|if|late|lock|new|nolate|otherwise|regexp|repeat|requires|return|surroundwith|unchecked|unless|using|while|yield)\b/,
+a],["typ",/^(?:array|bool|byte|char|decimal|double|float|int|list|long|object|sbyte|short|string|ulong|uint|ufloat|ulong|ushort|void)\b/,a],["lit",/^@[$_a-z][\w$@]*/i,a],["typ",/^@[A-Z]+[a-z][\w$@]*/,a],["pln",/^'?[$_a-z][\w$@]*/i,a],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,a,"0123456789"],["pun",/^.[^\s\w"-$'./@`]*/,a]]),["n","nemerle"]);
@@ -1 +1 @@
-PR.registerLangHandler(PR.sourceDecorator({keywords:"bool bytes default double enum extend extensions false fixed32 fixed64 float group import int32 int64 max message option optional package repeated required returns rpc service sfixed32 sfixed64 sint32 sint64 string syntax to true uint32 uint64",cStyleComments:true}),["proto"])
\ No newline at end of file
+PR.registerLangHandler(PR.sourceDecorator({keywords:"bytes,default,double,enum,extend,extensions,false,group,import,max,message,option,optional,package,repeated,required,returns,rpc,service,syntax,to,true",types:/^(bool|(double|s?fixed|[su]?int)(32|64)|float|string)\b/,cStyleComments:!0}),["proto"]);
@@ -1,2 +1,2 @@
-PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^(?:"(?:(?:""(?:""?(?!")|[^\\"]|\\.)*"{0,3})|(?:[^"\r\n\\]|\\.)*"?))/,null,'"'],["lit",/^`(?:[^\r\n\\`]|\\.)*`?/,null,"`"],["pun",/^[!#%&()*+,\-:;<=>?@\[\\\]^{|}~]+/,null,"!#%&()*+,-:;<=>?@[\\]^{|}~"]],[["str",/^'(?:[^\r\n\\']|\\(?:'|[^\r\n']+))'/],["lit",/^'[a-zA-Z_$][\w$]*(?!['$\w])/],["kwd",/^(?:abstract|case|catch|class|def|do|else|extends|final|finally|for|forSome|if|implicit|import|lazy|match|new|object|override|package|private|protected|requires|return|sealed|super|throw|trait|try|type|val|var|while|with|yield)\b/],
-["lit",/^(?:true|false|null|this)\b/],["lit",/^(?:(?:0(?:[0-7]+|X[0-9A-F]+))L?|(?:(?:0|[1-9][0-9]*)(?:(?:\.[0-9]+)?(?:E[+\-]?[0-9]+)?F?|L?))|\\.[0-9]+(?:E[+\-]?[0-9]+)?F?)/i],["typ",/^[$_]*[A-Z][_$A-Z0-9]*[a-z][\w$]*/],["pln",/^[$a-zA-Z_][\w$]*/],["com",/^\/(?:\/.*|\*(?:\/|\**[^*/])*(?:\*+\/?)?)/],["pun",/^(?:\.+|\/)/]]),["scala"])
\ No newline at end of file
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["str",/^"(?:""(?:""?(?!")|[^"\\]|\\.)*"{0,3}|(?:[^\n\r"\\]|\\.)*"?)/,null,'"'],["lit",/^`(?:[^\n\r\\`]|\\.)*`?/,null,"`"],["pun",/^[!#%&(--:-@[-^{-~]+/,null,"!#%&()*+,-:;<=>?@[\\]^{|}~"]],[["str",/^'(?:[^\n\r'\\]|\\(?:'|[^\n\r']+))'/],["lit",/^'[$A-Z_a-z][\w$]*(?![\w$'])/],["kwd",/^(?:abstract|case|catch|class|def|do|else|extends|final|finally|for|forSome|if|implicit|import|lazy|match|new|object|override|package|private|protected|requires|return|sealed|super|throw|trait|try|type|val|var|while|with|yield)\b/],
+["lit",/^(?:true|false|null|this)\b/],["lit",/^(?:0(?:[0-7]+|x[\da-f]+)l?|(?:0|[1-9]\d*)(?:(?:\.\d+)?(?:e[+-]?\d+)?f?|l?)|\\.\d+(?:e[+-]?\d+)?f?)/i],["typ",/^[$_]*[A-Z][\d$A-Z_]*[a-z][\w$]*/],["pln",/^[$A-Z_a-z][\w$]*/],["com",/^\/(?:\/.*|\*(?:\/|\**[^*/])*(?:\*+\/?)?)/],["pun",/^(?:\.+|\/)/]]),["scala"]);
@@ -1,2 +1,2 @@
-PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^(?:"(?:[^\"\\]|\\.)*"|'(?:[^\'\\]|\\.)*')/,null,"\"'"]],[["com",/^(?:--[^\r\n]*|\/\*[\s\S]*?(?:\*\/|$))/],["kwd",/^(?:ADD|ALL|ALTER|AND|ANY|AS|ASC|AUTHORIZATION|BACKUP|BEGIN|BETWEEN|BREAK|BROWSE|BULK|BY|CASCADE|CASE|CHECK|CHECKPOINT|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMN|COMMIT|COMPUTE|CONSTRAINT|CONTAINS|CONTAINSTABLE|CONTINUE|CONVERT|CREATE|CROSS|CURRENT|CURRENT_DATE|CURRENT_TIME|CURRENT_TIMESTAMP|CURRENT_USER|CURSOR|DATABASE|DBCC|DEALLOCATE|DECLARE|DEFAULT|DELETE|DENY|DESC|DISK|DISTINCT|DISTRIBUTED|DOUBLE|DROP|DUMMY|DUMP|ELSE|END|ERRLVL|ESCAPE|EXCEPT|EXEC|EXECUTE|EXISTS|EXIT|FETCH|FILE|FILLFACTOR|FOR|FOREIGN|FREETEXT|FREETEXTTABLE|FROM|FULL|FUNCTION|GOTO|GRANT|GROUP|HAVING|HOLDLOCK|IDENTITY|IDENTITYCOL|IDENTITY_INSERT|IF|IN|INDEX|INNER|INSERT|INTERSECT|INTO|IS|JOIN|KEY|KILL|LEFT|LIKE|LINENO|LOAD|NATIONAL|NOCHECK|NONCLUSTERED|NOT|NULL|NULLIF|OF|OFF|OFFSETS|ON|OPEN|OPENDATASOURCE|OPENQUERY|OPENROWSET|OPENXML|OPTION|OR|ORDER|OUTER|OVER|PERCENT|PLAN|PRECISION|PRIMARY|PRINT|PROC|PROCEDURE|PUBLIC|RAISERROR|READ|READTEXT|RECONFIGURE|REFERENCES|REPLICATION|RESTORE|RESTRICT|RETURN|REVOKE|RIGHT|ROLLBACK|ROWCOUNT|ROWGUIDCOL|RULE|SAVE|SCHEMA|SELECT|SESSION_USER|SET|SETUSER|SHUTDOWN|SOME|STATISTICS|SYSTEM_USER|TABLE|TEXTSIZE|THEN|TO|TOP|TRAN|TRANSACTION|TRIGGER|TRUNCATE|TSEQUAL|UNION|UNIQUE|UPDATE|UPDATETEXT|USE|USER|VALUES|VARYING|VIEW|WAITFOR|WHEN|WHERE|WHILE|WITH|WRITETEXT)(?=[^\w-]|$)/i,
-null],["lit",/^[+-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i],["pln",/^[a-z_][\w-]*/i],["pun",/^[^\w\t\n\r \xA0\"\'][^\w\t\n\r \xA0+\-\"\']*/]]),["sql"])
\ No newline at end of file
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["str",/^(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')/,null,"\"'"]],[["com",/^(?:--[^\n\r]*|\/\*[\S\s]*?(?:\*\/|$))/],["kwd",/^(?:add|all|alter|and|any|as|asc|authorization|backup|begin|between|break|browse|bulk|by|cascade|case|check|checkpoint|close|clustered|coalesce|collate|column|commit|compute|constraint|contains|containstable|continue|convert|create|cross|current|current_date|current_time|current_timestamp|current_user|cursor|database|dbcc|deallocate|declare|default|delete|deny|desc|disk|distinct|distributed|double|drop|dummy|dump|else|end|errlvl|escape|except|exec|execute|exists|exit|fetch|file|fillfactor|for|foreign|freetext|freetexttable|from|full|function|goto|grant|group|having|holdlock|identity|identitycol|identity_insert|if|in|index|inner|insert|intersect|into|is|join|key|kill|left|like|lineno|load|match|merge|national|nocheck|nonclustered|not|null|nullif|of|off|offsets|on|open|opendatasource|openquery|openrowset|openxml|option|or|order|outer|over|percent|plan|precision|primary|print|proc|procedure|public|raiserror|read|readtext|reconfigure|references|replication|restore|restrict|return|revoke|right|rollback|rowcount|rowguidcol|rule|save|schema|select|session_user|set|setuser|shutdown|some|statistics|system_user|table|textsize|then|to|top|tran|transaction|trigger|truncate|tsequal|union|unique|update|updatetext|use|user|using|values|varying|view|waitfor|when|where|while|with|writetext)(?=[^\w-]|$)/i,
+null],["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i],["pln",/^[_a-z][\w-]*/i],["pun",/^[^\w\t\n\r "'\xa0][^\w\t\n\r "'+\xa0-]*/]]),["sql"]);
@@ -0,0 +1 @@
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["com",/^%[^\n\r]*/,null,"%"]],[["kwd",/^\\[@-Za-z]+/],["kwd",/^\\./],["typ",/^[$&]/],["lit",/[+-]?(?:\.\d+|\d+(?:\.\d*)?)(cm|em|ex|in|pc|pt|bp|mm)/i],["pun",/^[()=[\]{}]+/]]),["latex","tex"]);
@@ -1,2 +1,2 @@
-PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0\u2028\u2029]+/,null,"\t\n\r \u00a0\u2028\u2029"],["str",/^(?:[\"\u201C\u201D](?:[^\"\u201C\u201D]|[\"\u201C\u201D]{2})(?:[\"\u201C\u201D]c|$)|[\"\u201C\u201D](?:[^\"\u201C\u201D]|[\"\u201C\u201D]{2})*(?:[\"\u201C\u201D]|$))/i,null,'"\u201c\u201d'],["com",/^[\'\u2018\u2019][^\r\n\u2028\u2029]*/,null,"'\u2018\u2019"]],[["kwd",/^(?:AddHandler|AddressOf|Alias|And|AndAlso|Ansi|As|Assembly|Auto|Boolean|ByRef|Byte|ByVal|Call|Case|Catch|CBool|CByte|CChar|CDate|CDbl|CDec|Char|CInt|Class|CLng|CObj|Const|CShort|CSng|CStr|CType|Date|Decimal|Declare|Default|Delegate|Dim|DirectCast|Do|Double|Each|Else|ElseIf|End|EndIf|Enum|Erase|Error|Event|Exit|Finally|For|Friend|Function|Get|GetType|GoSub|GoTo|Handles|If|Implements|Imports|In|Inherits|Integer|Interface|Is|Let|Lib|Like|Long|Loop|Me|Mod|Module|MustInherit|MustOverride|MyBase|MyClass|Namespace|New|Next|Not|NotInheritable|NotOverridable|Object|On|Option|Optional|Or|OrElse|Overloads|Overridable|Overrides|ParamArray|Preserve|Private|Property|Protected|Public|RaiseEvent|ReadOnly|ReDim|RemoveHandler|Resume|Return|Select|Set|Shadows|Shared|Short|Single|Static|Step|Stop|String|Structure|Sub|SyncLock|Then|Throw|To|Try|TypeOf|Unicode|Until|Variant|Wend|When|While|With|WithEvents|WriteOnly|Xor|EndIf|GoSub|Let|Variant|Wend)\b/i,
-null],["com",/^REM[^\r\n\u2028\u2029]*/i],["lit",/^(?:True\b|False\b|Nothing\b|\d+(?:E[+\-]?\d+[FRD]?|[FRDSIL])?|(?:&H[0-9A-F]+|&O[0-7]+)[SIL]?|\d*\.\d+(?:E[+\-]?\d+)?[FRD]?|#\s+(?:\d+[\-\/]\d+[\-\/]\d+(?:\s+\d+:\d+(?::\d+)?(\s*(?:AM|PM))?)?|\d+:\d+(?::\d+)?(\s*(?:AM|PM))?)\s+#)/i],["pln",/^(?:(?:[a-z]|_\w)\w*|\[(?:[a-z]|_\w)\w*\])/i],["pun",/^[^\w\t\n\r \"\'\[\]\xA0\u2018\u2019\u201C\u201D\u2028\u2029]+/],["pun",/^(?:\[|\])/]]),["vb","vbs"])
\ No newline at end of file
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0\u2028\u2029]+/,null,"\t\n\r Â\xa0

"],["str",/^(?:["\u201c\u201d](?:[^"\u201c\u201d]|["\u201c\u201d]{2})(?:["\u201c\u201d]c|$)|["\u201c\u201d](?:[^"\u201c\u201d]|["\u201c\u201d]{2})*(?:["\u201c\u201d]|$))/i,null,'"“”'],["com",/^['\u2018\u2019].*/,null,"'‘’"]],[["kwd",/^(?:addhandler|addressof|alias|and|andalso|ansi|as|assembly|auto|boolean|byref|byte|byval|call|case|catch|cbool|cbyte|cchar|cdate|cdbl|cdec|char|cint|class|clng|cobj|const|cshort|csng|cstr|ctype|date|decimal|declare|default|delegate|dim|directcast|do|double|each|else|elseif|end|endif|enum|erase|error|event|exit|finally|for|friend|function|get|gettype|gosub|goto|handles|if|implements|imports|in|inherits|integer|interface|is|let|lib|like|long|loop|me|mod|module|mustinherit|mustoverride|mybase|myclass|namespace|new|next|not|notinheritable|notoverridable|object|on|option|optional|or|orelse|overloads|overridable|overrides|paramarray|preserve|private|property|protected|public|raiseevent|readonly|redim|removehandler|resume|return|select|set|shadows|shared|short|single|static|step|stop|string|structure|sub|synclock|then|throw|to|try|typeof|unicode|until|variant|wend|when|while|with|withevents|writeonly|xor|endif|gosub|let|variant|wend)\b/i,
+null],["com",/^rem.*/i],["lit",/^(?:true\b|false\b|nothing\b|\d+(?:e[+-]?\d+[dfr]?|[dfilrs])?|(?:&h[\da-f]+|&o[0-7]+)[ils]?|\d*\.\d+(?:e[+-]?\d+)?[dfr]?|#\s+(?:\d+[/-]\d+[/-]\d+(?:\s+\d+:\d+(?::\d+)?(\s*(?:am|pm))?)?|\d+:\d+(?::\d+)?(\s*(?:am|pm))?)\s+#)/i],["pln",/^(?:(?:[a-z]|_\w)\w*|\[(?:[a-z]|_\w)\w*])/i],["pun",/^[^\w\t\n\r "'[\]\xa0\u2018\u2019\u201c\u201d\u2028\u2029]+/],["pun",/^(?:\[|])/]]),["vb","vbs"]);
@@ -1,3 +1,3 @@
-PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"]],[["str",/^(?:[BOX]?"(?:[^\"]|"")*"|'.')/i],["com",/^--[^\r\n]*/],["kwd",/^(?:abs|access|after|alias|all|and|architecture|array|assert|attribute|begin|block|body|buffer|bus|case|component|configuration|constant|disconnect|downto|else|elsif|end|entity|exit|file|for|function|generate|generic|group|guarded|if|impure|in|inertial|inout|is|label|library|linkage|literal|loop|map|mod|nand|new|next|nor|not|null|of|on|open|or|others|out|package|port|postponed|procedure|process|pure|range|record|register|reject|rem|report|return|rol|ror|select|severity|shared|signal|sla|sll|sra|srl|subtype|then|to|transport|type|unaffected|units|until|use|variable|wait|when|while|with|xnor|xor)(?=[^\w-]|$)/i,
-null],["typ",/^(?:bit|bit_vector|character|boolean|integer|real|time|string|severity_level|positive|natural|signed|unsigned|line|text|std_u?logic(?:_vector)?)(?=[^\w-]|$)/i,null],["typ",/^\'(?:ACTIVE|ASCENDING|BASE|DELAYED|DRIVING|DRIVING_VALUE|EVENT|HIGH|IMAGE|INSTANCE_NAME|LAST_ACTIVE|LAST_EVENT|LAST_VALUE|LEFT|LEFTOF|LENGTH|LOW|PATH_NAME|POS|PRED|QUIET|RANGE|REVERSE_RANGE|RIGHT|RIGHTOF|SIMPLE_NAME|STABLE|SUCC|TRANSACTION|VAL|VALUE)(?=[^\w-]|$)/i,null],["lit",/^\d+(?:_\d+)*(?:#[\w\\.]+#(?:[+\-]?\d+(?:_\d+)*)?|(?:\.\d+(?:_\d+)*)?(?:E[+\-]?\d+(?:_\d+)*)?)/i],
-["pln",/^(?:[a-z]\w*|\\[^\\]*\\)/i],["pun",/^[^\w\t\n\r \xA0\"\'][^\w\t\n\r \xA0\-\"\']*/]]),["vhdl","vhd"])
\ No newline at end of file
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"]],[["str",/^(?:[box]?"(?:[^"]|"")*"|'.')/i],["com",/^--[^\n\r]*/],["kwd",/^(?:abs|access|after|alias|all|and|architecture|array|assert|attribute|begin|block|body|buffer|bus|case|component|configuration|constant|disconnect|downto|else|elsif|end|entity|exit|file|for|function|generate|generic|group|guarded|if|impure|in|inertial|inout|is|label|library|linkage|literal|loop|map|mod|nand|new|next|nor|not|null|of|on|open|or|others|out|package|port|postponed|procedure|process|pure|range|record|register|reject|rem|report|return|rol|ror|select|severity|shared|signal|sla|sll|sra|srl|subtype|then|to|transport|type|unaffected|units|until|use|variable|wait|when|while|with|xnor|xor)(?=[^\w-]|$)/i,
+null],["typ",/^(?:bit|bit_vector|character|boolean|integer|real|time|string|severity_level|positive|natural|signed|unsigned|line|text|std_u?logic(?:_vector)?)(?=[^\w-]|$)/i,null],["typ",/^'(?:active|ascending|base|delayed|driving|driving_value|event|high|image|instance_name|last_active|last_event|last_value|left|leftof|length|low|path_name|pos|pred|quiet|range|reverse_range|right|rightof|simple_name|stable|succ|transaction|val|value)(?=[^\w-]|$)/i,null],["lit",/^\d+(?:_\d+)*(?:#[\w.\\]+#(?:[+-]?\d+(?:_\d+)*)?|(?:\.\d+(?:_\d+)*)?(?:e[+-]?\d+(?:_\d+)*)?)/i],
+["pln",/^(?:[a-z]\w*|\\[^\\]*\\)/i],["pun",/^[^\w\t\n\r "'\xa0][^\w\t\n\r "'\xa0-]*/]]),["vhdl","vhd"]);
@@ -1,2 +1,2 @@
-PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t \xA0a-gi-z0-9]+/,null,"\t \u00a0abcdefgijklmnopqrstuvwxyz0123456789"],["pun",/^[=*~\^\[\]]+/,null,"=*~^[]"]],[["lang-wiki.meta",/(?:^^|\r\n?|\n)(#[a-z]+)\b/],["lit",/^(?:[A-Z][a-z][a-z0-9]+[A-Z][a-z][a-zA-Z0-9]+)\b/],["lang-",/^\{\{\{([\s\S]+?)\}\}\}/],["lang-",/^`([^\r\n`]+)`/],["str",/^https?:\/\/[^\/?#\s]*(?:\/[^?#\s]*)?(?:\?[^#\s]*)?(?:#\S*)?/i],["pln",/^(?:\r\n|[\s\S])[^#=*~^A-Zh\{`\[\r\n]*/]]),["wiki"]);
-PR.registerLangHandler(PR.createSimpleLexer([["kwd",/^#[a-z]+/i,null,"#"]],[]),["wiki.meta"])
\ No newline at end of file
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\d\t a-gi-z\xa0]+/,null,"\t Â\xa0abcdefgijklmnopqrstuvwxyz0123456789"],["pun",/^[*=[\]^~]+/,null,"=*~^[]"]],[["lang-wiki.meta",/(?:^^|\r\n?|\n)(#[a-z]+)\b/],["lit",/^[A-Z][a-z][\da-z]+[A-Z][a-z][^\W_]+\b/],["lang-",/^{{{([\S\s]+?)}}}/],["lang-",/^`([^\n\r`]+)`/],["str",/^https?:\/\/[^\s#/?]*(?:\/[^\s#?]*)?(?:\?[^\s#]*)?(?:#\S*)?/i],["pln",/^(?:\r\n|[\S\s])[^\n\r#*=A-[^`h{~]*/]]),["wiki"]);
+PR.registerLangHandler(PR.createSimpleLexer([["kwd",/^#[a-z]+/i,null,"#"]],[]),["wiki.meta"]);
@@ -0,0 +1,3 @@
+PR.registerLangHandler(PR.createSimpleLexer([["var pln",/^\$[\w-]+/,null,"$"]],[["pln",/^[\s=][<>][\s=]/],["lit",/^@[\w-]+/],["tag",/^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["com",/^\(:[\S\s]*?:\)/],["pln",/^[(),/;[\]{}]$/],["str",/^(?:"(?:[^"\\{]|\\[\S\s])*(?:"|$)|'(?:[^'\\{]|\\[\S\s])*(?:'|$))/,null,"\"'"],["kwd",/^(?:xquery|where|version|variable|union|typeswitch|treat|to|then|text|stable|sortby|some|self|schema|satisfies|returns|return|ref|processing-instruction|preceding-sibling|preceding|precedes|parent|only|of|node|namespace|module|let|item|intersect|instance|in|import|if|function|for|follows|following-sibling|following|external|except|every|else|element|descending|descendant-or-self|descendant|define|default|declare|comment|child|cast|case|before|attribute|assert|ascending|as|ancestor-or-self|ancestor|after|eq|order|by|or|and|schema-element|document-node|node|at)\b/],
+["typ",/^(?:xs:yearMonthDuration|xs:unsignedLong|xs:time|xs:string|xs:short|xs:QName|xs:Name|xs:long|xs:integer|xs:int|xs:gYearMonth|xs:gYear|xs:gMonthDay|xs:gDay|xs:float|xs:duration|xs:double|xs:decimal|xs:dayTimeDuration|xs:dateTime|xs:date|xs:byte|xs:boolean|xs:anyURI|xf:yearMonthDuration)\b/,null],["fun pln",/^(?:xp:dereference|xinc:node-expand|xinc:link-references|xinc:link-expand|xhtml:restructure|xhtml:clean|xhtml:add-lists|xdmp:zip-manifest|xdmp:zip-get|xdmp:zip-create|xdmp:xquery-version|xdmp:word-convert|xdmp:with-namespaces|xdmp:version|xdmp:value|xdmp:user-roles|xdmp:user-last-login|xdmp:user|xdmp:url-encode|xdmp:url-decode|xdmp:uri-is-file|xdmp:uri-format|xdmp:uri-content-type|xdmp:unquote|xdmp:unpath|xdmp:triggers-database|xdmp:trace|xdmp:to-json|xdmp:tidy|xdmp:subbinary|xdmp:strftime|xdmp:spawn-in|xdmp:spawn|xdmp:sleep|xdmp:shutdown|xdmp:set-session-field|xdmp:set-response-encoding|xdmp:set-response-content-type|xdmp:set-response-code|xdmp:set-request-time-limit|xdmp:set|xdmp:servers|xdmp:server-status|xdmp:server-name|xdmp:server|xdmp:security-database|xdmp:security-assert|xdmp:schema-database|xdmp:save|xdmp:role-roles|xdmp:role|xdmp:rethrow|xdmp:restart|xdmp:request-timestamp|xdmp:request-status|xdmp:request-cancel|xdmp:request|xdmp:redirect-response|xdmp:random|xdmp:quote|xdmp:query-trace|xdmp:query-meters|xdmp:product-edition|xdmp:privilege-roles|xdmp:privilege|xdmp:pretty-print|xdmp:powerpoint-convert|xdmp:platform|xdmp:permission|xdmp:pdf-convert|xdmp:path|xdmp:octal-to-integer|xdmp:node-uri|xdmp:node-replace|xdmp:node-kind|xdmp:node-insert-child|xdmp:node-insert-before|xdmp:node-insert-after|xdmp:node-delete|xdmp:node-database|xdmp:mul64|xdmp:modules-root|xdmp:modules-database|xdmp:merging|xdmp:merge-cancel|xdmp:merge|xdmp:md5|xdmp:logout|xdmp:login|xdmp:log-level|xdmp:log|xdmp:lock-release|xdmp:lock-acquire|xdmp:load|xdmp:invoke-in|xdmp:invoke|xdmp:integer-to-octal|xdmp:integer-to-hex|xdmp:http-put|xdmp:http-post|xdmp:http-options|xdmp:http-head|xdmp:http-get|xdmp:http-delete|xdmp:hosts|xdmp:host-status|xdmp:host-name|xdmp:host|xdmp:hex-to-integer|xdmp:hash64|xdmp:hash32|xdmp:has-privilege|xdmp:groups|xdmp:group-serves|xdmp:group-servers|xdmp:group-name|xdmp:group-hosts|xdmp:group|xdmp:get-session-field-names|xdmp:get-session-field|xdmp:get-response-encoding|xdmp:get-response-code|xdmp:get-request-username|xdmp:get-request-user|xdmp:get-request-url|xdmp:get-request-protocol|xdmp:get-request-path|xdmp:get-request-method|xdmp:get-request-header-names|xdmp:get-request-header|xdmp:get-request-field-names|xdmp:get-request-field-filename|xdmp:get-request-field-content-type|xdmp:get-request-field|xdmp:get-request-client-certificate|xdmp:get-request-client-address|xdmp:get-request-body|xdmp:get-current-user|xdmp:get-current-roles|xdmp:get|xdmp:function-name|xdmp:function-module|xdmp:function|xdmp:from-json|xdmp:forests|xdmp:forest-status|xdmp:forest-restore|xdmp:forest-restart|xdmp:forest-name|xdmp:forest-delete|xdmp:forest-databases|xdmp:forest-counts|xdmp:forest-clear|xdmp:forest-backup|xdmp:forest|xdmp:filesystem-file|xdmp:filesystem-directory|xdmp:exists|xdmp:excel-convert|xdmp:eval-in|xdmp:eval|xdmp:estimate|xdmp:email|xdmp:element-content-type|xdmp:elapsed-time|xdmp:document-set-quality|xdmp:document-set-property|xdmp:document-set-properties|xdmp:document-set-permissions|xdmp:document-set-collections|xdmp:document-remove-properties|xdmp:document-remove-permissions|xdmp:document-remove-collections|xdmp:document-properties|xdmp:document-locks|xdmp:document-load|xdmp:document-insert|xdmp:document-get-quality|xdmp:document-get-properties|xdmp:document-get-permissions|xdmp:document-get-collections|xdmp:document-get|xdmp:document-forest|xdmp:document-delete|xdmp:document-add-properties|xdmp:document-add-permissions|xdmp:document-add-collections|xdmp:directory-properties|xdmp:directory-locks|xdmp:directory-delete|xdmp:directory-create|xdmp:directory|xdmp:diacritic-less|xdmp:describe|xdmp:default-permissions|xdmp:default-collections|xdmp:databases|xdmp:database-restore-validate|xdmp:database-restore-status|xdmp:database-restore-cancel|xdmp:database-restore|xdmp:database-name|xdmp:database-forests|xdmp:database-backup-validate|xdmp:database-backup-status|xdmp:database-backup-purge|xdmp:database-backup-cancel|xdmp:database-backup|xdmp:database|xdmp:collection-properties|xdmp:collection-locks|xdmp:collection-delete|xdmp:collation-canonical-uri|xdmp:castable-as|xdmp:can-grant-roles|xdmp:base64-encode|xdmp:base64-decode|xdmp:architecture|xdmp:apply|xdmp:amp-roles|xdmp:amp|xdmp:add64|xdmp:add-response-header|xdmp:access|trgr:trigger-set-recursive|trgr:trigger-set-permissions|trgr:trigger-set-name|trgr:trigger-set-module|trgr:trigger-set-event|trgr:trigger-set-description|trgr:trigger-remove-permissions|trgr:trigger-module|trgr:trigger-get-permissions|trgr:trigger-enable|trgr:trigger-disable|trgr:trigger-database-online-event|trgr:trigger-data-event|trgr:trigger-add-permissions|trgr:remove-trigger|trgr:property-content|trgr:pre-commit|trgr:post-commit|trgr:get-trigger-by-id|trgr:get-trigger|trgr:document-scope|trgr:document-content|trgr:directory-scope|trgr:create-trigger|trgr:collection-scope|trgr:any-property-content|thsr:set-entry|thsr:remove-term|thsr:remove-synonym|thsr:remove-entry|thsr:query-lookup|thsr:lookup|thsr:load|thsr:insert|thsr:expand|thsr:add-synonym|spell:suggest-detailed|spell:suggest|spell:remove-word|spell:make-dictionary|spell:load|spell:levenshtein-distance|spell:is-correct|spell:insert|spell:double-metaphone|spell:add-word|sec:users-collection|sec:user-set-roles|sec:user-set-password|sec:user-set-name|sec:user-set-description|sec:user-set-default-permissions|sec:user-set-default-collections|sec:user-remove-roles|sec:user-privileges|sec:user-get-roles|sec:user-get-description|sec:user-get-default-permissions|sec:user-get-default-collections|sec:user-doc-permissions|sec:user-doc-collections|sec:user-add-roles|sec:unprotect-collection|sec:uid-for-name|sec:set-realm|sec:security-version|sec:security-namespace|sec:security-installed|sec:security-collection|sec:roles-collection|sec:role-set-roles|sec:role-set-name|sec:role-set-description|sec:role-set-default-permissions|sec:role-set-default-collections|sec:role-remove-roles|sec:role-privileges|sec:role-get-roles|sec:role-get-description|sec:role-get-default-permissions|sec:role-get-default-collections|sec:role-doc-permissions|sec:role-doc-collections|sec:role-add-roles|sec:remove-user|sec:remove-role-from-users|sec:remove-role-from-role|sec:remove-role-from-privileges|sec:remove-role-from-amps|sec:remove-role|sec:remove-privilege|sec:remove-amp|sec:protect-collection|sec:privileges-collection|sec:privilege-set-roles|sec:privilege-set-name|sec:privilege-remove-roles|sec:privilege-get-roles|sec:privilege-add-roles|sec:priv-doc-permissions|sec:priv-doc-collections|sec:get-user-names|sec:get-unique-elem-id|sec:get-role-names|sec:get-role-ids|sec:get-privilege|sec:get-distinct-permissions|sec:get-collection|sec:get-amp|sec:create-user-with-role|sec:create-user|sec:create-role|sec:create-privilege|sec:create-amp|sec:collections-collection|sec:collection-set-permissions|sec:collection-remove-permissions|sec:collection-get-permissions|sec:collection-add-permissions|sec:check-admin|sec:amps-collection|sec:amp-set-roles|sec:amp-remove-roles|sec:amp-get-roles|sec:amp-doc-permissions|sec:amp-doc-collections|sec:amp-add-roles|search:unparse|search:suggest|search:snippet|search:search|search:resolve-nodes|search:resolve|search:remove-constraint|search:parse|search:get-default-options|search:estimate|search:check-options|prof:value|prof:reset|prof:report|prof:invoke|prof:eval|prof:enable|prof:disable|prof:allowed|ppt:clean|pki:template-set-request|pki:template-set-name|pki:template-set-key-type|pki:template-set-key-options|pki:template-set-description|pki:template-in-use|pki:template-get-version|pki:template-get-request|pki:template-get-name|pki:template-get-key-type|pki:template-get-key-options|pki:template-get-id|pki:template-get-description|pki:need-certificate|pki:is-temporary|pki:insert-trusted-certificates|pki:insert-template|pki:insert-signed-certificates|pki:insert-certificate-revocation-list|pki:get-trusted-certificate-ids|pki:get-template-ids|pki:get-template-certificate-authority|pki:get-template-by-name|pki:get-template|pki:get-pending-certificate-requests-xml|pki:get-pending-certificate-requests-pem|pki:get-pending-certificate-request|pki:get-certificates-for-template-xml|pki:get-certificates-for-template|pki:get-certificates|pki:get-certificate-xml|pki:get-certificate-pem|pki:get-certificate|pki:generate-temporary-certificate-if-necessary|pki:generate-temporary-certificate|pki:generate-template-certificate-authority|pki:generate-certificate-request|pki:delete-template|pki:delete-certificate|pki:create-template|pdf:make-toc|pdf:insert-toc-headers|pdf:get-toc|pdf:clean|p:status-transition|p:state-transition|p:remove|p:pipelines|p:insert|p:get-by-id|p:get|p:execute|p:create|p:condition|p:collection|p:action|ooxml:runs-merge|ooxml:package-uris|ooxml:package-parts-insert|ooxml:package-parts|msword:clean|mcgm:polygon|mcgm:point|mcgm:geospatial-query-from-elements|mcgm:geospatial-query|mcgm:circle|math:tanh|math:tan|math:sqrt|math:sinh|math:sin|math:pow|math:modf|math:log10|math:log|math:ldexp|math:frexp|math:fmod|math:floor|math:fabs|math:exp|math:cosh|math:cos|math:ceil|math:atan2|math:atan|math:asin|math:acos|map:put|map:map|map:keys|map:get|map:delete|map:count|map:clear|lnk:to|lnk:remove|lnk:insert|lnk:get|lnk:from|lnk:create|kml:polygon|kml:point|kml:interior-polygon|kml:geospatial-query-from-elements|kml:geospatial-query|kml:circle|kml:box|gml:polygon|gml:point|gml:interior-polygon|gml:geospatial-query-from-elements|gml:geospatial-query|gml:circle|gml:box|georss:point|georss:geospatial-query|georss:circle|geo:polygon|geo:point|geo:interior-polygon|geo:geospatial-query-from-elements|geo:geospatial-query|geo:circle|geo:box|fn:zero-or-one|fn:years-from-duration|fn:year-from-dateTime|fn:year-from-date|fn:upper-case|fn:unordered|fn:true|fn:translate|fn:trace|fn:tokenize|fn:timezone-from-time|fn:timezone-from-dateTime|fn:timezone-from-date|fn:sum|fn:subtract-dateTimes-yielding-yearMonthDuration|fn:subtract-dateTimes-yielding-dayTimeDuration|fn:substring-before|fn:substring-after|fn:substring|fn:subsequence|fn:string-to-codepoints|fn:string-pad|fn:string-length|fn:string-join|fn:string|fn:static-base-uri|fn:starts-with|fn:seconds-from-time|fn:seconds-from-duration|fn:seconds-from-dateTime|fn:round-half-to-even|fn:round|fn:root|fn:reverse|fn:resolve-uri|fn:resolve-QName|fn:replace|fn:remove|fn:QName|fn:prefix-from-QName|fn:position|fn:one-or-more|fn:number|fn:not|fn:normalize-unicode|fn:normalize-space|fn:node-name|fn:node-kind|fn:nilled|fn:namespace-uri-from-QName|fn:namespace-uri-for-prefix|fn:namespace-uri|fn:name|fn:months-from-duration|fn:month-from-dateTime|fn:month-from-date|fn:minutes-from-time|fn:minutes-from-duration|fn:minutes-from-dateTime|fn:min|fn:max|fn:matches|fn:lower-case|fn:local-name-from-QName|fn:local-name|fn:last|fn:lang|fn:iri-to-uri|fn:insert-before|fn:index-of|fn:in-scope-prefixes|fn:implicit-timezone|fn:idref|fn:id|fn:hours-from-time|fn:hours-from-duration|fn:hours-from-dateTime|fn:floor|fn:false|fn:expanded-QName|fn:exists|fn:exactly-one|fn:escape-uri|fn:escape-html-uri|fn:error|fn:ends-with|fn:encode-for-uri|fn:empty|fn:document-uri|fn:doc-available|fn:doc|fn:distinct-values|fn:distinct-nodes|fn:default-collation|fn:deep-equal|fn:days-from-duration|fn:day-from-dateTime|fn:day-from-date|fn:data|fn:current-time|fn:current-dateTime|fn:current-date|fn:count|fn:contains|fn:concat|fn:compare|fn:collection|fn:codepoints-to-string|fn:codepoint-equal|fn:ceiling|fn:boolean|fn:base-uri|fn:avg|fn:adjust-time-to-timezone|fn:adjust-dateTime-to-timezone|fn:adjust-date-to-timezone|fn:abs|feed:unsubscribe|feed:subscription|feed:subscribe|feed:request|feed:item|feed:description|excel:clean|entity:enrich|dom:set-pipelines|dom:set-permissions|dom:set-name|dom:set-evaluation-context|dom:set-domain-scope|dom:set-description|dom:remove-pipeline|dom:remove-permissions|dom:remove|dom:get|dom:evaluation-context|dom:domains|dom:domain-scope|dom:create|dom:configuration-set-restart-user|dom:configuration-set-permissions|dom:configuration-set-evaluation-context|dom:configuration-set-default-domain|dom:configuration-get|dom:configuration-create|dom:collection|dom:add-pipeline|dom:add-permissions|dls:retention-rules|dls:retention-rule-remove|dls:retention-rule-insert|dls:retention-rule|dls:purge|dls:node-expand|dls:link-references|dls:link-expand|dls:documents-query|dls:document-versions-query|dls:document-version-uri|dls:document-version-query|dls:document-version-delete|dls:document-version-as-of|dls:document-version|dls:document-update|dls:document-unmanage|dls:document-set-quality|dls:document-set-property|dls:document-set-properties|dls:document-set-permissions|dls:document-set-collections|dls:document-retention-rules|dls:document-remove-properties|dls:document-remove-permissions|dls:document-remove-collections|dls:document-purge|dls:document-manage|dls:document-is-managed|dls:document-insert-and-manage|dls:document-include-query|dls:document-history|dls:document-get-permissions|dls:document-extract-part|dls:document-delete|dls:document-checkout-status|dls:document-checkout|dls:document-checkin|dls:document-add-properties|dls:document-add-permissions|dls:document-add-collections|dls:break-checkout|dls:author-query|dls:as-of-query|dbk:convert|dbg:wait|dbg:value|dbg:stopped|dbg:stop|dbg:step|dbg:status|dbg:stack|dbg:out|dbg:next|dbg:line|dbg:invoke|dbg:function|dbg:finish|dbg:expr|dbg:eval|dbg:disconnect|dbg:detach|dbg:continue|dbg:connect|dbg:clear|dbg:breakpoints|dbg:break|dbg:attached|dbg:attach|cvt:save-converted-documents|cvt:part-uri|cvt:destination-uri|cvt:basepath|cvt:basename|cts:words|cts:word-query-weight|cts:word-query-text|cts:word-query-options|cts:word-query|cts:word-match|cts:walk|cts:uris|cts:uri-match|cts:train|cts:tokenize|cts:thresholds|cts:stem|cts:similar-query-weight|cts:similar-query-nodes|cts:similar-query|cts:shortest-distance|cts:search|cts:score|cts:reverse-query-weight|cts:reverse-query-nodes|cts:reverse-query|cts:remainder|cts:registered-query-weight|cts:registered-query-options|cts:registered-query-ids|cts:registered-query|cts:register|cts:query|cts:quality|cts:properties-query-query|cts:properties-query|cts:polygon-vertices|cts:polygon|cts:point-longitude|cts:point-latitude|cts:point|cts:or-query-queries|cts:or-query|cts:not-query-weight|cts:not-query-query|cts:not-query|cts:near-query-weight|cts:near-query-queries|cts:near-query-options|cts:near-query-distance|cts:near-query|cts:highlight|cts:geospatial-co-occurrences|cts:frequency|cts:fitness|cts:field-words|cts:field-word-query-weight|cts:field-word-query-text|cts:field-word-query-options|cts:field-word-query-field-name|cts:field-word-query|cts:field-word-match|cts:entity-highlight|cts:element-words|cts:element-word-query-weight|cts:element-word-query-text|cts:element-word-query-options|cts:element-word-query-element-name|cts:element-word-query|cts:element-word-match|cts:element-values|cts:element-value-ranges|cts:element-value-query-weight|cts:element-value-query-text|cts:element-value-query-options|cts:element-value-query-element-name|cts:element-value-query|cts:element-value-match|cts:element-value-geospatial-co-occurrences|cts:element-value-co-occurrences|cts:element-range-query-weight|cts:element-range-query-value|cts:element-range-query-options|cts:element-range-query-operator|cts:element-range-query-element-name|cts:element-range-query|cts:element-query-query|cts:element-query-element-name|cts:element-query|cts:element-pair-geospatial-values|cts:element-pair-geospatial-value-match|cts:element-pair-geospatial-query-weight|cts:element-pair-geospatial-query-region|cts:element-pair-geospatial-query-options|cts:element-pair-geospatial-query-longitude-name|cts:element-pair-geospatial-query-latitude-name|cts:element-pair-geospatial-query-element-name|cts:element-pair-geospatial-query|cts:element-pair-geospatial-boxes|cts:element-geospatial-values|cts:element-geospatial-value-match|cts:element-geospatial-query-weight|cts:element-geospatial-query-region|cts:element-geospatial-query-options|cts:element-geospatial-query-element-name|cts:element-geospatial-query|cts:element-geospatial-boxes|cts:element-child-geospatial-values|cts:element-child-geospatial-value-match|cts:element-child-geospatial-query-weight|cts:element-child-geospatial-query-region|cts:element-child-geospatial-query-options|cts:element-child-geospatial-query-element-name|cts:element-child-geospatial-query-child-name|cts:element-child-geospatial-query|cts:element-child-geospatial-boxes|cts:element-attribute-words|cts:element-attribute-word-query-weight|cts:element-attribute-word-query-text|cts:element-attribute-word-query-options|cts:element-attribute-word-query-element-name|cts:element-attribute-word-query-attribute-name|cts:element-attribute-word-query|cts:element-attribute-word-match|cts:element-attribute-values|cts:element-attribute-value-ranges|cts:element-attribute-value-query-weight|cts:element-attribute-value-query-text|cts:element-attribute-value-query-options|cts:element-attribute-value-query-element-name|cts:element-attribute-value-query-attribute-name|cts:element-attribute-value-query|cts:element-attribute-value-match|cts:element-attribute-value-geospatial-co-occurrences|cts:element-attribute-value-co-occurrences|cts:element-attribute-range-query-weight|cts:element-attribute-range-query-value|cts:element-attribute-range-query-options|cts:element-attribute-range-query-operator|cts:element-attribute-range-query-element-name|cts:element-attribute-range-query-attribute-name|cts:element-attribute-range-query|cts:element-attribute-pair-geospatial-values|cts:element-attribute-pair-geospatial-value-match|cts:element-attribute-pair-geospatial-query-weight|cts:element-attribute-pair-geospatial-query-region|cts:element-attribute-pair-geospatial-query-options|cts:element-attribute-pair-geospatial-query-longitude-name|cts:element-attribute-pair-geospatial-query-latitude-name|cts:element-attribute-pair-geospatial-query-element-name|cts:element-attribute-pair-geospatial-query|cts:element-attribute-pair-geospatial-boxes|cts:document-query-uris|cts:document-query|cts:distance|cts:directory-query-uris|cts:directory-query-depth|cts:directory-query|cts:destination|cts:deregister|cts:contains|cts:confidence|cts:collections|cts:collection-query-uris|cts:collection-query|cts:collection-match|cts:classify|cts:circle-radius|cts:circle-center|cts:circle|cts:box-west|cts:box-south|cts:box-north|cts:box-east|cts:box|cts:bearing|cts:arc-intersection|cts:and-query-queries|cts:and-query-options|cts:and-query|cts:and-not-query-positive-query|cts:and-not-query-negative-query|cts:and-not-query|css:get|css:convert|cpf:success|cpf:failure|cpf:document-set-state|cpf:document-set-processing-status|cpf:document-set-last-updated|cpf:document-set-error|cpf:document-get-state|cpf:document-get-processing-status|cpf:document-get-last-updated|cpf:document-get-error|cpf:check-transition|alert:spawn-matching-actions|alert:rule-user-id-query|alert:rule-set-user-id|alert:rule-set-query|alert:rule-set-options|alert:rule-set-name|alert:rule-set-description|alert:rule-set-action|alert:rule-remove|alert:rule-name-query|alert:rule-insert|alert:rule-id-query|alert:rule-get-user-id|alert:rule-get-query|alert:rule-get-options|alert:rule-get-name|alert:rule-get-id|alert:rule-get-description|alert:rule-get-action|alert:rule-action-query|alert:remove-triggers|alert:make-rule|alert:make-log-action|alert:make-config|alert:make-action|alert:invoke-matching-actions|alert:get-my-rules|alert:get-all-rules|alert:get-actions|alert:find-matching-rules|alert:create-triggers|alert:config-set-uri|alert:config-set-trigger-ids|alert:config-set-options|alert:config-set-name|alert:config-set-description|alert:config-set-cpf-domain-names|alert:config-set-cpf-domain-ids|alert:config-insert|alert:config-get-uri|alert:config-get-trigger-ids|alert:config-get-options|alert:config-get-name|alert:config-get-id|alert:config-get-description|alert:config-get-cpf-domain-names|alert:config-get-cpf-domain-ids|alert:config-get|alert:config-delete|alert:action-set-options|alert:action-set-name|alert:action-set-module-root|alert:action-set-module-db|alert:action-set-module|alert:action-set-description|alert:action-remove|alert:action-insert|alert:action-get-options|alert:action-get-name|alert:action-get-module-root|alert:action-get-module-db|alert:action-get-module|alert:action-get-description|zero-or-one|years-from-duration|year-from-dateTime|year-from-date|upper-case|unordered|true|translate|trace|tokenize|timezone-from-time|timezone-from-dateTime|timezone-from-date|sum|subtract-dateTimes-yielding-yearMonthDuration|subtract-dateTimes-yielding-dayTimeDuration|substring-before|substring-after|substring|subsequence|string-to-codepoints|string-pad|string-length|string-join|string|static-base-uri|starts-with|seconds-from-time|seconds-from-duration|seconds-from-dateTime|round-half-to-even|round|root|reverse|resolve-uri|resolve-QName|replace|remove|QName|prefix-from-QName|position|one-or-more|number|not|normalize-unicode|normalize-space|node-name|node-kind|nilled|namespace-uri-from-QName|namespace-uri-for-prefix|namespace-uri|name|months-from-duration|month-from-dateTime|month-from-date|minutes-from-time|minutes-from-duration|minutes-from-dateTime|min|max|matches|lower-case|local-name-from-QName|local-name|last|lang|iri-to-uri|insert-before|index-of|in-scope-prefixes|implicit-timezone|idref|id|hours-from-time|hours-from-duration|hours-from-dateTime|floor|false|expanded-QName|exists|exactly-one|escape-uri|escape-html-uri|error|ends-with|encode-for-uri|empty|document-uri|doc-available|doc|distinct-values|distinct-nodes|default-collation|deep-equal|days-from-duration|day-from-dateTime|day-from-date|data|current-time|current-dateTime|current-date|count|contains|concat|compare|collection|codepoints-to-string|codepoint-equal|ceiling|boolean|base-uri|avg|adjust-time-to-timezone|adjust-dateTime-to-timezone|adjust-date-to-timezone|abs)\b/],
+["pln",/^[\w:-]+/],["pln",/^[\t\n\r \xa0]+/]]),["xq","xquery"]);
@@ -1,2 +1,2 @@
-PR.registerLangHandler(PR.createSimpleLexer([["pun",/^[:|>?]+/,null,":|>?"],["dec",/^%(?:YAML|TAG)[^#\r\n]+/,null,"%"],["typ",/^[&]\S+/,null,"&"],["typ",/^!\S*/,null,"!"],["str",/^"(?:[^\\"]|\\.)*(?:"|$)/,null,'"'],["str",/^'(?:[^']|'')*(?:'|$)/,null,"'"],["com",/^#[^\r\n]*/,null,"#"],["pln",/^\s+/,null," \t\r\n"]],[["dec",/^(?:---|\.\.\.)(?:[\r\n]|$)/],["pun",/^-/],["kwd",/^\w+:[ \r\n]/],["pln",/^\w+/]]),
-["yaml","yml"])
\ No newline at end of file
+var a=null;
+PR.registerLangHandler(PR.createSimpleLexer([["pun",/^[:>?|]+/,a,":|>?"],["dec",/^%(?:YAML|TAG)[^\n\r#]+/,a,"%"],["typ",/^&\S+/,a,"&"],["typ",/^!\S*/,a,"!"],["str",/^"(?:[^"\\]|\\.)*(?:"|$)/,a,'"'],["str",/^'(?:[^']|'')*(?:'|$)/,a,"'"],["com",/^#[^\n\r]*/,a,"#"],["pln",/^\s+/,a," \t\r\n"]],[["dec",/^(?:---|\.\.\.)(?:[\n\r]|$)/],["pun",/^-/],["kwd",/^\w+:[\n\r ]/],["pln",/^\w+/]]),["yaml","yml"]);
@@ -1,33 +1,28 @@
-window.PR_SHOULD_USE_CONTINUATION=true;window.PR_TAB_WIDTH=8;window.PR_normalizedHtml=window.PR=window.prettyPrintOne=window.prettyPrint=void 0;window._pr_isIE6=function(){var y=navigator&&navigator.userAgent&&navigator.userAgent.match(/\bMSIE ([678])\./);y=y?+y[1]:false;window._pr_isIE6=function(){return y};return y};
-(function(){function y(b){return b.replace(L,"&amp;").replace(M,"&lt;").replace(N,"&gt;")}function H(b,f,i){switch(b.nodeType){case 1:var o=b.tagName.toLowerCase();f.push("<",o);var l=b.attributes,n=l.length;if(n){if(i){for(var r=[],j=n;--j>=0;)r[j]=l[j];r.sort(function(q,m){return q.name<m.name?-1:q.name===m.name?0:1});l=r}for(j=0;j<n;++j){r=l[j];r.specified&&f.push(" ",r.name.toLowerCase(),'="',r.value.replace(L,"&amp;").replace(M,"&lt;").replace(N,"&gt;").replace(X,"&quot;"),'"')}}f.push(">");
-for(l=b.firstChild;l;l=l.nextSibling)H(l,f,i);if(b.firstChild||!/^(?:br|link|img)$/.test(o))f.push("</",o,">");break;case 3:case 4:f.push(y(b.nodeValue));break}}function O(b){function f(c){if(c.charAt(0)!=="\\")return c.charCodeAt(0);switch(c.charAt(1)){case "b":return 8;case "t":return 9;case "n":return 10;case "v":return 11;case "f":return 12;case "r":return 13;case "u":case "x":return parseInt(c.substring(2),16)||c.charCodeAt(1);case "0":case "1":case "2":case "3":case "4":case "5":case "6":case "7":return parseInt(c.substring(1),
-8);default:return c.charCodeAt(1)}}function i(c){if(c<32)return(c<16?"\\x0":"\\x")+c.toString(16);c=String.fromCharCode(c);if(c==="\\"||c==="-"||c==="["||c==="]")c="\\"+c;return c}function o(c){var d=c.substring(1,c.length-1).match(RegExp("\\\\u[0-9A-Fa-f]{4}|\\\\x[0-9A-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\s\\S]|-|[^-\\\\]","g"));c=[];for(var a=[],k=d[0]==="^",e=k?1:0,h=d.length;e<h;++e){var g=d[e];switch(g){case "\\B":case "\\b":case "\\D":case "\\d":case "\\S":case "\\s":case "\\W":case "\\w":c.push(g);
-continue}g=f(g);var s;if(e+2<h&&"-"===d[e+1]){s=f(d[e+2]);e+=2}else s=g;a.push([g,s]);if(!(s<65||g>122)){s<65||g>90||a.push([Math.max(65,g)|32,Math.min(s,90)|32]);s<97||g>122||a.push([Math.max(97,g)&-33,Math.min(s,122)&-33])}}a.sort(function(v,w){return v[0]-w[0]||w[1]-v[1]});d=[];g=[NaN,NaN];for(e=0;e<a.length;++e){h=a[e];if(h[0]<=g[1]+1)g[1]=Math.max(g[1],h[1]);else d.push(g=h)}a=["["];k&&a.push("^");a.push.apply(a,c);for(e=0;e<d.length;++e){h=d[e];a.push(i(h[0]));if(h[1]>h[0]){h[1]+1>h[0]&&a.push("-");
-a.push(i(h[1]))}}a.push("]");return a.join("")}function l(c){for(var d=c.source.match(RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g")),a=d.length,k=[],e=0,h=0;e<a;++e){var g=d[e];if(g==="(")++h;else if("\\"===g.charAt(0))if((g=+g.substring(1))&&g<=h)k[g]=-1}for(e=1;e<k.length;++e)if(-1===k[e])k[e]=++n;for(h=e=0;e<a;++e){g=d[e];if(g==="("){++h;if(k[h]===undefined)d[e]="(?:"}else if("\\"===
-g.charAt(0))if((g=+g.substring(1))&&g<=h)d[e]="\\"+k[h]}for(h=e=0;e<a;++e)if("^"===d[e]&&"^"!==d[e+1])d[e]="";if(c.ignoreCase&&r)for(e=0;e<a;++e){g=d[e];c=g.charAt(0);if(g.length>=2&&c==="[")d[e]=o(g);else if(c!=="\\")d[e]=g.replace(/[a-zA-Z]/g,function(s){s=s.charCodeAt(0);return"["+String.fromCharCode(s&-33,s|32)+"]"})}return d.join("")}for(var n=0,r=false,j=false,q=0,m=b.length;q<m;++q){var t=b[q];if(t.ignoreCase)j=true;else if(/[a-z]/i.test(t.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi,
-""))){r=true;j=false;break}}var p=[];q=0;for(m=b.length;q<m;++q){t=b[q];if(t.global||t.multiline)throw Error(""+t);p.push("(?:"+l(t)+")")}return RegExp(p.join("|"),j?"gi":"g")}function Y(b){var f=0;return function(i){for(var o=null,l=0,n=0,r=i.length;n<r;++n)switch(i.charAt(n)){case "\t":o||(o=[]);o.push(i.substring(l,n));l=b-f%b;for(f+=l;l>=0;l-=16)o.push("                ".substring(0,l));l=n+1;break;case "\n":f=0;break;default:++f}if(!o)return i;o.push(i.substring(l));return o.join("")}}function I(b,
-f,i,o){if(f){b={source:f,c:b};i(b);o.push.apply(o,b.d)}}function B(b,f){var i={},o;(function(){for(var r=b.concat(f),j=[],q={},m=0,t=r.length;m<t;++m){var p=r[m],c=p[3];if(c)for(var d=c.length;--d>=0;)i[c.charAt(d)]=p;p=p[1];c=""+p;if(!q.hasOwnProperty(c)){j.push(p);q[c]=null}}j.push(/[\0-\uffff]/);o=O(j)})();var l=f.length;function n(r){for(var j=r.c,q=[j,z],m=0,t=r.source.match(o)||[],p={},c=0,d=t.length;c<d;++c){var a=t[c],k=p[a],e=void 0,h;if(typeof k==="string")h=false;else{var g=i[a.charAt(0)];
-if(g){e=a.match(g[1]);k=g[0]}else{for(h=0;h<l;++h){g=f[h];if(e=a.match(g[1])){k=g[0];break}}e||(k=z)}if((h=k.length>=5&&"lang-"===k.substring(0,5))&&!(e&&typeof e[1]==="string")){h=false;k=P}h||(p[a]=k)}g=m;m+=a.length;if(h){h=e[1];var s=a.indexOf(h),v=s+h.length;if(e[2]){v=a.length-e[2].length;s=v-h.length}k=k.substring(5);I(j+g,a.substring(0,s),n,q);I(j+g+s,h,Q(k,h),q);I(j+g+v,a.substring(v),n,q)}else q.push(j+g,k)}r.d=q}return n}function x(b){var f=[],i=[];if(b.tripleQuotedStrings)f.push([A,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,
-null,"'\""]);else b.multiLineStrings?f.push([A,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"]):f.push([A,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"]);b.verbatimStrings&&i.push([A,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null]);if(b.hashComments)if(b.cStyleComments){f.push([C,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"]);i.push([A,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,
-null])}else f.push([C,/^#[^\r\n]*/,null,"#"]);if(b.cStyleComments){i.push([C,/^\/\/[^\r\n]*/,null]);i.push([C,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}b.regexLiterals&&i.push(["lang-regex",RegExp("^"+Z+"(/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/)")]);b=b.keywords.replace(/^\s+|\s+$/g,"");b.length&&i.push([R,RegExp("^(?:"+b.replace(/\s+/g,"|")+")\\b"),null]);f.push([z,/^\s+/,null," \r\n\t\u00a0"]);i.push([J,/^@[a-z_$][a-z_$@0-9]*/i,null],[S,/^@?[A-Z]+[a-z][A-Za-z_$@0-9]*/,
-null],[z,/^[a-z_$][a-z_$@0-9]*/i,null],[J,/^(?:0x[a-f0-9]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+\-]?\d+)?)[a-z]*/i,null,"0123456789"],[E,/^.[^\s\w\.$@\'\"\`\/\#]*/,null]);return B(f,i)}function $(b){function f(D){if(D>r){if(j&&j!==q){n.push("</span>");j=null}if(!j&&q){j=q;n.push('<span class="',j,'">')}var T=y(p(i.substring(r,D))).replace(e?d:c,"$1&#160;");e=k.test(T);n.push(T.replace(a,s));r=D}}var i=b.source,o=b.g,l=b.d,n=[],r=0,j=null,q=null,m=0,t=0,p=Y(window.PR_TAB_WIDTH),c=/([\r\n ]) /g,
-d=/(^| ) /gm,a=/\r\n?|\n/g,k=/[ \r\n]$/,e=true,h=window._pr_isIE6();h=h?b.b.tagName==="PRE"?h===6?"&#160;\r\n":h===7?"&#160;<br>\r":"&#160;\r":"&#160;<br />":"<br />";var g=b.b.className.match(/\blinenums\b(?::(\d+))?/),s;if(g){for(var v=[],w=0;w<10;++w)v[w]=h+'</li><li class="L'+w+'">';var F=g[1]&&g[1].length?g[1]-1:0;n.push('<ol class="linenums"><li class="L',F%10,'"');F&&n.push(' value="',F+1,'"');n.push(">");s=function(){var D=v[++F%10];return j?"</span>"+D+'<span class="'+j+'">':D}}else s=h;
-for(;;)if(m<o.length?t<l.length?o[m]<=l[t]:true:false){f(o[m]);if(j){n.push("</span>");j=null}n.push(o[m+1]);m+=2}else if(t<l.length){f(l[t]);q=l[t+1];t+=2}else break;f(i.length);j&&n.push("</span>");g&&n.push("</li></ol>");b.a=n.join("")}function u(b,f){for(var i=f.length;--i>=0;){var o=f[i];if(G.hasOwnProperty(o))"console"in window&&console.warn("cannot override language handler %s",o);else G[o]=b}}function Q(b,f){b&&G.hasOwnProperty(b)||(b=/^\s*</.test(f)?"default-markup":"default-code");return G[b]}
-function U(b){var f=b.f,i=b.e;b.a=f;try{var o,l=f.match(aa);f=[];var n=0,r=[];if(l)for(var j=0,q=l.length;j<q;++j){var m=l[j];if(m.length>1&&m.charAt(0)==="<"){if(!ba.test(m))if(ca.test(m)){f.push(m.substring(9,m.length-3));n+=m.length-12}else if(da.test(m)){f.push("\n");++n}else if(m.indexOf(V)>=0&&m.replace(/\s(\w+)\s*=\s*(?:\"([^\"]*)\"|'([^\']*)'|(\S+))/g,' $1="$2$3$4"').match(/[cC][lL][aA][sS][sS]=\"[^\"]*\bnocode\b/)){var t=m.match(W)[2],p=1,c;c=j+1;a:for(;c<q;++c){var d=l[c].match(W);if(d&&
-d[2]===t)if(d[1]==="/"){if(--p===0)break a}else++p}if(c<q){r.push(n,l.slice(j,c+1).join(""));j=c}else r.push(n,m)}else r.push(n,m)}else{var a;p=m;var k=p.indexOf("&");if(k<0)a=p;else{for(--k;(k=p.indexOf("&#",k+1))>=0;){var e=p.indexOf(";",k);if(e>=0){var h=p.substring(k+3,e),g=10;if(h&&h.charAt(0)==="x"){h=h.substring(1);g=16}var s=parseInt(h,g);isNaN(s)||(p=p.substring(0,k)+String.fromCharCode(s)+p.substring(e+1))}}a=p.replace(ea,"<").replace(fa,">").replace(ga,"'").replace(ha,'"').replace(ia," ").replace(ja,
-"&")}f.push(a);n+=a.length}}o={source:f.join(""),h:r};var v=o.source;b.source=v;b.c=0;b.g=o.h;Q(i,v)(b);$(b)}catch(w){if("console"in window)console.log(w&&w.stack?w.stack:w)}}var A="str",R="kwd",C="com",S="typ",J="lit",E="pun",z="pln",P="src",V="nocode",Z=function(){for(var b=["!","!=","!==","#","%","%=","&","&&","&&=","&=","(","*","*=","+=",",","-=","->","/","/=",":","::",";","<","<<","<<=","<=","=","==","===",">",">=",">>",">>=",">>>",">>>=","?","@","[","^","^=","^^","^^=","{","|","|=","||","||=",
-"~","break","case","continue","delete","do","else","finally","instanceof","return","throw","try","typeof"],f="(?:^^|[+-]",i=0;i<b.length;++i)f+="|"+b[i].replace(/([^=<>:&a-z])/g,"\\$1");f+=")\\s*";return f}(),L=/&/g,M=/</g,N=/>/g,X=/\"/g,ea=/&lt;/g,fa=/&gt;/g,ga=/&apos;/g,ha=/&quot;/g,ja=/&amp;/g,ia=/&nbsp;/g,ka=/[\r\n]/g,K=null,aa=RegExp("[^<]+|<!--[\\s\\S]*?--\>|<!\\[CDATA\\[[\\s\\S]*?\\]\\]>|</?[a-zA-Z](?:[^>\"']|'[^']*'|\"[^\"]*\")*>|<","g"),ba=/^<\!--/,ca=/^<!\[CDATA\[/,da=/^<br\b/i,W=/^<(\/?)([a-zA-Z][a-zA-Z0-9]*)/,
-la=x({keywords:"break continue do else for if return while auto case char const default double enum extern float goto int long register short signed sizeof static struct switch typedef union unsigned void volatile catch class delete false import new operator private protected public this throw true try typeof alignof align_union asm axiom bool concept concept_map const_cast constexpr decltype dynamic_cast explicit export friend inline late_check mutable namespace nullptr reinterpret_cast static_assert static_cast template typeid typename using virtual wchar_t where break continue do else for if return while auto case char const default double enum extern float goto int long register short signed sizeof static struct switch typedef union unsigned void volatile catch class delete false import new operator private protected public this throw true try typeof abstract boolean byte extends final finally implements import instanceof null native package strictfp super synchronized throws transient as base by checked decimal delegate descending event fixed foreach from group implicit in interface internal into is lock object out override orderby params partial readonly ref sbyte sealed stackalloc string select uint ulong unchecked unsafe ushort var break continue do else for if return while auto case char const default double enum extern float goto int long register short signed sizeof static struct switch typedef union unsigned void volatile catch class delete false import new operator private protected public this throw true try typeof debugger eval export function get null set undefined var with Infinity NaN caller delete die do dump elsif eval exit foreach for goto if import last local my next no our print package redo require sub undef unless until use wantarray while BEGIN END break continue do else for if return while and as assert class def del elif except exec finally from global import in is lambda nonlocal not or pass print raise try with yield False True None break continue do else for if return while alias and begin case class def defined elsif end ensure false in module next nil not or redo rescue retry self super then true undef unless until when yield BEGIN END break continue do else for if return while case done elif esac eval fi function in local set then until ",
-hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true}),G={};u(la,["default-code"]);u(B([],[[z,/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],[C,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[E,/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup",
-"htm","html","mxml","xhtml","xml","xsl"]);u(B([[z,/^[\s]+/,null," \t\r\n"],["atv",/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[E,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],
-["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);u(B([],[["atv",/^[\s\S]+/]]),["uq.val"]);u(x({keywords:"break continue do else for if return while auto case char const default double enum extern float goto int long register short signed sizeof static struct switch typedef union unsigned void volatile catch class delete false import new operator private protected public this throw true try typeof alignof align_union asm axiom bool concept concept_map const_cast constexpr decltype dynamic_cast explicit export friend inline late_check mutable namespace nullptr reinterpret_cast static_assert static_cast template typeid typename using virtual wchar_t where ",
-hashComments:true,cStyleComments:true}),["c","cc","cpp","cxx","cyc","m"]);u(x({keywords:"null true false"}),["json"]);u(x({keywords:"break continue do else for if return while auto case char const default double enum extern float goto int long register short signed sizeof static struct switch typedef union unsigned void volatile catch class delete false import new operator private protected public this throw true try typeof abstract boolean byte extends final finally implements import instanceof null native package strictfp super synchronized throws transient as base by checked decimal delegate descending event fixed foreach from group implicit in interface internal into is lock object out override orderby params partial readonly ref sbyte sealed stackalloc string select uint ulong unchecked unsafe ushort var ",
-hashComments:true,cStyleComments:true,verbatimStrings:true}),["cs"]);u(x({keywords:"break continue do else for if return while auto case char const default double enum extern float goto int long register short signed sizeof static struct switch typedef union unsigned void volatile catch class delete false import new operator private protected public this throw true try typeof abstract boolean byte extends final finally implements import instanceof null native package strictfp super synchronized throws transient ",
-cStyleComments:true}),["java"]);u(x({keywords:"break continue do else for if return while case done elif esac eval fi function in local set then until ",hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);u(x({keywords:"break continue do else for if return while and as assert class def del elif except exec finally from global import in is lambda nonlocal not or pass print raise try with yield False True None ",hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);
-u(x({keywords:"caller delete die do dump elsif eval exit foreach for goto if import last local my next no our print package redo require sub undef unless until use wantarray while BEGIN END ",hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);u(x({keywords:"break continue do else for if return while alias and begin case class def defined elsif end ensure false in module next nil not or redo rescue retry self super then true undef unless until when yield BEGIN END ",hashComments:true,
-multiLineStrings:true,regexLiterals:true}),["rb"]);u(x({keywords:"break continue do else for if return while auto case char const default double enum extern float goto int long register short signed sizeof static struct switch typedef union unsigned void volatile catch class delete false import new operator private protected public this throw true try typeof debugger eval export function get null set undefined var with Infinity NaN ",cStyleComments:true,regexLiterals:true}),["js"]);u(B([],[[A,/^[\s\S]+/]]),
-["regex"]);window.PR_normalizedHtml=H;window.prettyPrintOne=function(b,f){var i={f:b,e:f};U(i);return i.a};window.prettyPrint=function(b){function f(){for(var t=window.PR_SHOULD_USE_CONTINUATION?j.now()+250:Infinity;q<o.length&&j.now()<t;q++){var p=o[q];if(p.className&&p.className.indexOf("prettyprint")>=0){var c=p.className.match(/\blang-(\w+)\b/);if(c)c=c[1];for(var d=false,a=p.parentNode;a;a=a.parentNode)if((a.tagName==="pre"||a.tagName==="code"||a.tagName==="xmp")&&a.className&&a.className.indexOf("prettyprint")>=
-0){d=true;break}if(!d){a=p;if(null===K){d=document.createElement("PRE");d.appendChild(document.createTextNode('<!DOCTYPE foo PUBLIC "foo bar">\n<foo />'));K=!/</.test(d.innerHTML)}if(K){d=a.innerHTML;if("XMP"===a.tagName)d=y(d);else{a=a;if("PRE"===a.tagName)a=true;else if(ka.test(d)){var k="";if(a.currentStyle)k=a.currentStyle.whiteSpace;else if(window.getComputedStyle)k=window.getComputedStyle(a,null).whiteSpace;a=!k||k==="pre"}else a=true;a||(d=d.replace(/(<br\s*\/?>)[\r\n]+/g,"$1").replace(/(?:[\r\n]+[ \t]*)+/g,
-" "))}d=d}else{d=[];for(a=a.firstChild;a;a=a.nextSibling)H(a,d);d=d.join("")}d=d.replace(/(?:\r\n?|\n)$/,"");m={f:d,e:c,b:p};U(m);if(p=m.a){c=m.b;if("XMP"===c.tagName){d=document.createElement("PRE");for(a=0;a<c.attributes.length;++a){k=c.attributes[a];if(k.specified)if(k.name.toLowerCase()==="class")d.className=k.value;else d.setAttribute(k.name,k.value)}d.innerHTML=p;c.parentNode.replaceChild(d,c)}else c.innerHTML=p}}}}if(q<o.length)setTimeout(f,250);else b&&b()}for(var i=[document.getElementsByTagName("pre"),
-document.getElementsByTagName("code"),document.getElementsByTagName("xmp")],o=[],l=0;l<i.length;++l)for(var n=0,r=i[l].length;n<r;++n)o.push(i[l][n]);i=null;var j=Date;j.now||(j={now:function(){return(new Date).getTime()}});var q=0,m;f()};window.PR={combinePrefixPatterns:O,createSimpleLexer:B,registerLangHandler:u,sourceDecorator:x,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:C,PR_DECLARATION:"dec",PR_KEYWORD:R,PR_LITERAL:J,PR_NOCODE:V,PR_PLAIN:z,PR_PUNCTUATION:E,PR_SOURCE:P,PR_STRING:A,
-PR_TAG:"tag",PR_TYPE:S}})()
\ No newline at end of file
+var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;
+(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a=
+[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&"-"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=["["];o&&b.push("^");b.push.apply(b,a);for(c=0;c<
+f.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j==="("?++i:"\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j==="("?(++i,d[i]===void 0&&(f[c]="(?:")):"\\"===j.charAt(0)&&
+(j=+j.substring(1))&&j<=i&&(f[c]="\\"+d[i]);for(i=c=0;c<b;++c)"^"===f[c]&&"^"!==f[c+1]&&(f[c]="");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){s=!0;l=!1;break}}for(var r=
+{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(""+g);n.push("(?:"+y(g)+")")}return RegExp(n.join("|"),l?"gi":"g")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if("BR"===g||"LI"===g)h[s]="\n",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\r\n?/g,"\n"):g.replace(/[\t\n\r ]+/g," "),h[s]=g,t[s<<1]=y,y+=g.length,
+t[s++<<1|1]=a)}}var e=/(?:^|\s)nocode(?:\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);m(a);return{a:h.join("").replace(/\n$/,""),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,"pln"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0,c;if(typeof b===
+"string")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b="pln")}if((c=b.length>=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m),
+l=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,
+q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/,
+q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g,
+"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a),
+a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e}
+for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0].setAttribute("value",
+m);var r=s.createElement("OL");r.className="linenums";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className="L"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode("\xa0")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*</.test(m)?"default-markup":"default-code";return A[a]}function E(a){var m=
+a.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\bMSIE\b/.test(navigator.userAgent),m=/\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,"\r"));i.nodeValue=
+j;var u=i.ownerDocument,v=u.createElement("SPAN");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
+"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"],
+H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],
+J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+
+I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),
+["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",
+/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),
+["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes",
+hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf("prettyprint")>=0){var k=k.match(g),f,b;if(b=
+!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.length?setTimeout(m,
+250):a&&a()}for(var e=[document.getElementsByTagName("pre"),document.getElementsByTagName("code"),document.getElementsByTagName("xmp")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\blang(?:uage)?-([\w.]+)(?!\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",
+PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ"}})();
@@ -112,7 +112,7 @@
       %= tag 'tr', $i ? (class => 'important') : undef, begin
         <td class="key"><%= $key %>.</td>
         <td class="value">
-          %== $code->($value)
+          %= $code->($value)
         </td>
       % end
     % end
@@ -130,13 +130,13 @@
       <div id="context">
         <table>
           % for my $line (@{$e->lines_before}) {
-            %== $cv->($line->[0], $line->[1])
+            %= $cv->($line->[0], $line->[1])
           % }
           % if (defined $e->line->[1]) {
-            %== $cv->($e->line->[0], $e->line->[1], 1)
+            %= $cv->($e->line->[0], $e->line->[1], 1)
           % }
           % for my $line (@{$e->lines_after}) {
-            %== $cv->($line->[0], $line->[1])
+            %= $cv->($line->[0], $line->[1])
           % }
         </table>
       </div>
@@ -144,11 +144,11 @@
         <div id="insight">
           <table>
             % for my $line (@{$e->lines_before}) {
-              %== $cv->($line->[0], $line->[2])
+              %= $cv->($line->[0], $line->[2])
             % }
-            %== $cv->($e->line->[0], $e->line->[2], 1)
+            %= $cv->($e->line->[0], $e->line->[2], 1)
             % for my $line (@{$e->lines_after}) {
-              %== $cv->($line->[0], $line->[2])
+              %= $cv->($line->[0], $line->[2])
             % }
           </table>
         </div>
@@ -178,7 +178,7 @@
               <div class="file"><%= $frame->[1] %></div>
               <div class="code preview">
                 %= "$frame->[2]."
-                %== $code->($line)
+                %= $code->($line)
               </div>
             % }
           % }
@@ -195,33 +195,33 @@
     <div class="box infobox" id="request">
       <table>
         % my $req = $self->req;
-        %== $kv->(Method => $req->method)
+        %= $kv->(Method => $req->method)
         % my $url = $req->url;
-        %== $kv->(Path => $url->to_string)
-        %== $kv->(Base => $url->base->to_string)
-        %== $kv->(Parameters => dumper $req->params->to_hash)
-        %== $kv->(Stash => dumper $snapshot)
-        %== $kv->(Session => dumper session)
-        %== $kv->(Version => $req->version)
+        %= $kv->(Path => $url->to_string)
+        %= $kv->(Base => $url->base->to_string)
+        %= $kv->(Parameters => dumper $req->params->to_hash)
+        %= $kv->(Stash => dumper $snapshot)
+        %= $kv->(Session => dumper session)
+        %= $kv->(Version => $req->version)
         % for my $name (@{$self->req->headers->names}) {
           % my $value = $self->req->headers->header($name);
-          %== $kv->($name, $value)
+          %= $kv->($name, $value)
         % }
       </table>
     </div>
     <div class="box infobox" id="more">
       <div id="infos">
         <table>
-          %== $kv->(Perl => "$] ($^O)")
+          %= $kv->(Perl => "$] ($^O)")
           % my $version  = $Mojolicious::VERSION;
           % my $codename = $Mojolicious::CODENAME;
-          %== $kv->(Mojolicious => "$version ($codename)")
-          %== $kv->(Home => app->home)
-          %== $kv->(Include => dumper \@INC)
-          %== $kv->(PID => $$)
-          %== $kv->(Name => $0)
-          %== $kv->(Executable => $^X)
-          %== $kv->(Time => scalar localtime(time))
+          %= $kv->(Mojolicious => "$version ($codename)")
+          %= $kv->(Home => app->home)
+          %= $kv->(Include => dumper \@INC)
+          %= $kv->(PID => $$)
+          %= $kv->(Name => $0)
+          %= $kv->(Executable => $^X)
+          %= $kv->(Time => scalar localtime(time))
         </table>
       </div>
       <div class="tap">tap for more</div>
@@ -63,12 +63,12 @@
       <ul>
         % for my $section (@$sections) {
           <li>
-            %== $link->(splice @$section, 0, 2)
+            %= $link->(splice @$section, 0, 2)
             % if (@$section) {
               <ul>
                 % while (@$section) {
                   <li>
-                    %== $link->(splice @$section, 0, 2)
+                    %= $link->(splice @$section, 0, 2)
                   </li>
                 % }
               </ul>
@@ -3,6 +3,7 @@ use Mojo::Base 'Mojo';
 
 use Carp 'croak';
 use Mojolicious::Commands;
+use Mojolicious::Controller;
 use Mojolicious::Plugins;
 use Mojolicious::Renderer;
 use Mojolicious::Routes;
@@ -25,14 +26,14 @@ has secret   => sub {
   $self->log->debug('Your secret passphrase needs to be changed!!!');
 
   # Default to application name
-  return ref $self;
+  ref $self;
 };
 has sessions => sub { Mojolicious::Sessions->new };
 has static   => sub { Mojolicious::Static->new };
 has types    => sub { Mojolicious::Types->new };
 
 our $CODENAME = 'Smiling Face With Sunglasses';
-our $VERSION  = '1.42';
+our $VERSION  = '1.48';
 
 # "These old doomsday devices are dangerously unstable.
 #  I'll rest easier not knowing where they are."
@@ -46,18 +47,8 @@ sub AUTOLOAD {
   croak qq/Can't locate object method "$method" via package "$package"/
     unless my $helper = $self->renderer->helpers->{$method};
 
-  # Load controller class
-  my $class = $self->controller_class;
-  if (my $e = Mojo::Loader->load($class)) {
-    $self->log->error(
-      ref $e
-      ? qq/Can't load controller class "$class": $e/
-      : qq/Controller class "$class" doesn't exist./
-    );
-  }
-
   # Call helper with fresh controller
-  return $class->new(app => $self)->$helper(@_);
+  $self->controller_class->new(app => $self)->$helper(@_);
 }
 
 sub DESTROY { }
@@ -73,19 +64,18 @@ sub new {
       my $self = shift;
       my $tx   = Mojo::Transaction::HTTP->new;
       $self->plugins->run_hook(after_build_tx => ($tx, $self));
-      return $tx;
+      $tx;
     }
   );
 
+  # Root directories
+  my $home = $self->home;
+  $self->renderer->root($home->rel_dir('templates'));
+  $self->static->root($home->rel_dir('public'));
+
+  # Default to application namespace
   my $r = $self->routes;
   $r->namespace(ref $self);
-  my $renderer = $self->renderer;
-  my $static   = $self->static;
-  my $home     = $self->home;
-
-  # Root
-  $renderer->root($home->rel_dir('templates'));
-  $static->root($home->rel_dir('public'));
 
   # Hide own controller methods
   $r->hide(qw/AUTOLOAD DESTROY client cookie delayed finish finished/);
@@ -101,7 +91,8 @@ sub new {
     if -w $home->rel_file('log');
 
   # Load default plugins
-  $self->plugin('agent_condition');
+  $self->plugin('callback_condition');
+  $self->plugin('header_condition');
   $self->plugin('default_helpers');
   $self->plugin('tag_helpers');
   $self->plugin('epl_renderer');
@@ -119,7 +110,7 @@ sub new {
   # Startup
   $self->startup(@_);
 
-  return $self;
+  $self;
 }
 
 # "Amy, technology isn't intrinsically good or evil. It's how it's used.
@@ -140,7 +131,7 @@ sub defaults {
     $self->{defaults}->{$key} = $values->{$key};
   }
 
-  return $self;
+  $self;
 }
 
 # The default dispatchers with exception handling
@@ -163,23 +154,16 @@ sub dispatch {
   return if $res->code;
   if (my $code = ($tx->req->error)[1]) { $res->code($code) }
   elsif ($tx->is_websocket) { $res->code(426) }
-  if ($self->routes->dispatch($c)) { $c->render_not_found unless $res->code }
+  unless ($self->routes->dispatch($c)) {
+    $c->render_not_found
+      unless $res->code;
+  }
 }
 
 # "Bite my shiny metal ass!"
 sub handler {
   my ($self, $tx) = @_;
 
-  # Load controller class
-  my $class = $self->controller_class;
-  if (my $e = Mojo::Loader->load($class)) {
-    $self->log->error(
-      ref $e
-      ? qq/Can't load controller class "$class": $e/
-      : qq/Controller class "$class" doesn't exist./
-    );
-  }
-
   # Embedded application
   my $stash = {};
   if ($tx->can('stash')) {
@@ -190,7 +174,8 @@ sub handler {
   # Build default controller and process
   my $defaults = $self->defaults;
   @{$stash}{keys %$defaults} = values %$defaults;
-  my $c = $class->new(app => $self, stash => $stash, tx => $tx);
+  my $c =
+    $self->controller_class->new(app => $self, stash => $stash, tx => $tx);
   unless (eval { $self->on_process->($self, $c); 1 }) {
     $self->log->fatal("Processing request failed: $@");
     $tx->res->code(500);
@@ -198,8 +183,7 @@ sub handler {
   }
 
   # Delayed
-  $self->log->debug(
-    'Waiting for delayed response, forgot to render or resume?')
+  $self->log->debug('Nothing has been rendered, assuming delayed response.')
     unless $stash->{'mojo.rendered'} || $tx->is_writing;
 }
 
@@ -239,7 +223,7 @@ sub start {
   $ENV{MOJO_APP} = ref $class ? $class : $class->new;
 
   # Start!
-  return Mojolicious::Commands->start(@_);
+  Mojolicious::Commands->start(@_);
 }
 
 # This will run once at startup
@@ -320,12 +304,12 @@ TLS, Bonjour, IDNA, Comet (long polling), chunking and multipart support.
 
 =item *
 
-Builtin async IO web server supporting epoll, kqueue, UNIX domain sockets and
-hot deployment, perfect for embedding.
+Built-in async IO web server supporting epoll, kqueue, UNIX domain sockets
+and hot deployment, perfect for embedding.
 
 =item *
 
-Automatic CGI, FastCGI, and L<PSGI> detection.
+Automatic CGI, FastCGI and L<PSGI> detection.
 
 =item *
 
@@ -353,8 +337,8 @@ These three lines are a whole web application.
 
   app->start;
 
-To run this example with the built-in development server just put the code
-into a file and execute it with C<perl>.
+To run this example with the built-in development web server just put the
+code into a file and execute it with C<perl>.
 
   % perl hello.pl daemon
   Server available at http://127.0.0.1:3000.
@@ -375,10 +359,9 @@ Web development for humans, making hard things possible and everything fun.
   get '/time' => 'clock';
 
   # RESTful web service sending JSON responses
-  get '/:offset' => sub {
-    my $self   = shift;
-    my $offset = $self->param('offset') || 23;
-    $self->render_json({list => [0 .. $offset]});
+  get '/list/:offset' => sub {
+    my $self = shift;
+    $self->render_json({list => [0 .. $self->param('offset')]});
   };
 
   # Scrape and return information from remote sites
@@ -423,9 +406,8 @@ A controller collects several actions together.
 
   # RESTful web service sending JSON responses
   sub restful {
-    my $self   = shift;
-    my $offset = $self->param('offset') || 23;
-    $self->render_json({list => [0 .. $offset]});
+    my $self = shift;
+    $self->render_json({list => [0 .. $self->param('offset')]});
   }
 
   # Scrape and return information from remote sites
@@ -473,7 +455,7 @@ especially when working in a team.
     # (paths are relative to the controller)
     $example->get('/')->to('#hello');
     $example->get('/time')->to('#clock');
-    $example->get('/:offset')->to('#restful');
+    $example->get('/list/:offset')->to('#restful');
 
     # All common HTTP verbs are supported
     $example->post('/title')->to('#title');
@@ -783,9 +765,9 @@ examples.
 
 =over 2
 
-=item L<Mojolicious::Plugin::AgentCondition>
+=item L<Mojolicious::Plugin::CallbackCondition>
 
-Route condition for C<User-Agent> headers.
+Very versatile route condition for arbitrary callbacks.
 
 =item L<Mojolicious::Plugin::Charset>
 
@@ -819,6 +801,10 @@ Internationalization helpers.
 
 JSON configuration files.
 
+=item L<Mojolicious::Plugin::Mount>
+
+Mount whole L<Mojolicious> applications.
+
 =item L<Mojolicious::Plugin::PodRenderer>
 
 Renderer for POD files and documentation browser.
@@ -900,9 +886,9 @@ development. jQuery is designed to change the way that you write JavaScript.
 
 Licensed under the MIT License, L<http://creativecommons.org/licenses/MIT>.
 
-=head2 Prettify.js
+=head2 prettify.js
 
-  Version 21-Jul-2010
+  Version 1-Jun-2011
 
 A Javascript module and CSS file that allows syntax highlighting of source
 code snippets in an html page.
@@ -957,6 +943,8 @@ Adam Kennedy
 
 Adriano Ferreira
 
+Al Newkirk
+
 Alex Salimon
 
 Alexey Likhatskiy
@@ -1085,6 +1073,8 @@ Robert Hicks
 
 Robin Lee
 
+Roland Lammel
+
 Ryan Jendoubi
 
 Sascha Kiefer
@@ -33,7 +33,7 @@ sub content_is {
   local $Test::Builder::Level = $Test::Builder::Level + 1;
   Test::More::is($self->_get_content($tx), $value, $desc);
 
-  return $self;
+  $self;
 }
 
 sub content_isnt {
@@ -44,7 +44,7 @@ sub content_isnt {
   local $Test::Builder::Level = $Test::Builder::Level + 1;
   Test::More::isnt($self->_get_content($tx), $value, $desc);
 
-  return $self;
+  $self;
 }
 
 sub content_like {
@@ -55,7 +55,7 @@ sub content_like {
   local $Test::Builder::Level = $Test::Builder::Level + 1;
   Test::More::like($self->_get_content($tx), $regex, $desc);
 
-  return $self;
+  $self;
 }
 
 sub content_unlike {
@@ -66,7 +66,7 @@ sub content_unlike {
   local $Test::Builder::Level = $Test::Builder::Level + 1;
   Test::More::unlike($self->_get_content($tx), $regex, $desc);
 
-  return $self;
+  $self;
 }
 
 # "Marge, I can't wear a pink shirt to work.
@@ -78,7 +78,7 @@ sub content_type_is {
   local $Test::Builder::Level = $Test::Builder::Level + 1;
   Test::More::is($tx->res->headers->content_type,
     $type, "Content-Type: $type");
-  return $self;
+  $self;
 }
 
 sub content_type_isnt {
@@ -87,7 +87,7 @@ sub content_type_isnt {
   local $Test::Builder::Level = $Test::Builder::Level + 1;
   Test::More::isnt($tx->res->headers->content_type,
     $type, "not Content-Type: $type");
-  return $self;
+  $self;
 }
 
 sub content_type_like {
@@ -98,7 +98,7 @@ sub content_type_like {
   local $Test::Builder::Level = $Test::Builder::Level + 1;
   Test::More::like($tx->res->headers->content_type, $regex, $desc);
 
-  return $self;
+  $self;
 }
 
 sub content_type_unlike {
@@ -109,7 +109,7 @@ sub content_type_unlike {
   local $Test::Builder::Level = $Test::Builder::Level + 1;
   Test::More::unlike($tx->res->headers->content_type, $regex, $desc);
 
-  return $self;
+  $self;
 }
 
 # "A job's a job. I mean, take me.
@@ -122,7 +122,7 @@ sub element_exists {
   $desc ||= qq/"$selector" exists/;
   local $Test::Builder::Level = $Test::Builder::Level + 1;
   Test::More::ok($self->tx->res->dom->at($selector), $desc);
-  return $self;
+  $self;
 }
 
 sub element_exists_not {
@@ -130,7 +130,7 @@ sub element_exists_not {
   $desc ||= qq/"$selector" exists not/;
   local $Test::Builder::Level = $Test::Builder::Level + 1;
   Test::More::ok(!$self->tx->res->dom->at($selector), $desc);
-  return $self;
+  $self;
 }
 
 sub get_ok  { shift->_request_ok('get',  @_) }
@@ -144,7 +144,7 @@ sub header_is {
   Test::More::is(scalar $tx->res->headers->header($name),
     $value, "$name: " . ($value ? $value : ''));
 
-  return $self;
+  $self;
 }
 
 sub header_isnt {
@@ -155,7 +155,7 @@ sub header_isnt {
   Test::More::isnt(scalar $tx->res->headers->header($name),
     $value, "not $name: " . ($value ? $value : ''));
 
-  return $self;
+  $self;
 }
 
 sub header_like {
@@ -166,7 +166,7 @@ sub header_like {
   local $Test::Builder::Level = $Test::Builder::Level + 1;
   Test::More::like(scalar $tx->res->headers->header($name), $regex, $desc);
 
-  return $self;
+  $self;
 }
 
 sub header_unlike {
@@ -177,7 +177,7 @@ sub header_unlike {
   local $Test::Builder::Level = $Test::Builder::Level + 1;
   Test::More::unlike(scalar $tx->res->headers->header($name), $regex, $desc);
 
-  return $self;
+  $self;
 }
 
 sub json_content_is {
@@ -188,7 +188,7 @@ sub json_content_is {
   local $Test::Builder::Level = $Test::Builder::Level + 1;
   Test::More::is_deeply($tx->res->json, $struct, $desc);
 
-  return $self;
+  $self;
 }
 
 # "God bless those pagans."
@@ -207,7 +207,7 @@ sub post_form_ok {
   local $Test::Builder::Level = $Test::Builder::Level + 1;
   Test::More::ok($self->tx->is_done, $desc);
 
-  return $self;
+  $self;
 }
 
 # "WHO IS FONZY!?! Don't they teach you anything at school?"
@@ -218,7 +218,7 @@ sub reset_session {
   $self->ua->cookie_jar->empty;
   $self->ua->max_redirects($self->max_redirects);
   $self->tx(undef);
-  return $self;
+  $self;
 }
 
 # "Internet! Is that thing still around?"
@@ -230,7 +230,7 @@ sub status_is {
   local $Test::Builder::Level = $Test::Builder::Level + 1;
   Test::More::is($self->tx->res->code, $status, "$status $message");
 
-  return $self;
+  $self;
 }
 
 sub status_isnt {
@@ -241,7 +241,7 @@ sub status_isnt {
   local $Test::Builder::Level = $Test::Builder::Level + 1;
   Test::More::isnt($self->tx->res->code, $status, "not $status $message");
 
-  return $self;
+  $self;
 }
 
 sub text_is {
@@ -255,7 +255,7 @@ sub text_is {
   local $Test::Builder::Level = $Test::Builder::Level + 1;
   Test::More::is($text, $value, $desc);
 
-  return $self;
+  $self;
 }
 
 sub text_isnt {
@@ -269,7 +269,7 @@ sub text_isnt {
   local $Test::Builder::Level = $Test::Builder::Level + 1;
   Test::More::isnt($text, $value, $desc);
 
-  return $self;
+  $self;
 }
 
 # "Hello, my name is Barney Gumble, and I'm an alcoholic.
@@ -286,7 +286,7 @@ sub text_like {
   local $Test::Builder::Level = $Test::Builder::Level + 1;
   Test::More::like($text, $regex, $desc);
 
-  return $self;
+  $self;
 }
 
 sub text_unlike {
@@ -300,7 +300,7 @@ sub text_unlike {
   local $Test::Builder::Level = $Test::Builder::Level + 1;
   Test::More::unlike($text, $regex, $desc);
 
-  return $self;
+  $self;
 }
 
 sub _get_content {
@@ -314,29 +314,27 @@ sub _get_content {
   # Content
   my $content = $tx->res->body;
   decode $charset, $content if $charset;
-  return $content;
+  $content;
 }
 
 # "Are you sure this is the Sci-Fi Convention? It's full of nerds!"
 sub _request_ok {
   my ($self, $method, $url, $headers, $body) = @_;
-
-  my $desc = "$method $url";
-  utf8::encode $desc;
-
-  # Body without headers
   $body = $headers if !ref $headers && @_ > 3;
   $headers = {} if !ref $headers;
 
+  # Perform request against application
   my $ua = $self->ua;
   $ua->app($self->app);
   $ua->max_redirects($self->max_redirects);
   $self->tx($ua->$method($url, %$headers, $body));
   local $Test::Builder::Level = $Test::Builder::Level + 2;
   my ($error, $code) = $self->tx->error;
+  my $desc = "$method $url";
+  utf8::encode $desc;
   Test::More::ok(!$error || $code, $desc);
 
-  return $self;
+  $self;
 }
 
 1;
@@ -69,7 +69,7 @@ sub _request {
   my ($message, $code) = $tx->error;
   warn qq/Problem loading URL "$_[0]". ($message)\n/ if $message && !$code;
 
-  return $tx->res;
+  $tx->res;
 }
 
 1;
@@ -58,7 +58,8 @@ hypnotoad - Hypnotoad HTTP 1.1 And WebSocket Server
 
 =head1 SYNOPSIS
 
-    hypnotoad myapp.pl
+  % hypnotoad --help
+  % hypnotoad myapp.pl
 
 =head1 DESCRIPTION
 
@@ -28,7 +28,7 @@ mojo - The Mojolicious Command System
 
 =head1 SYNOPSIS
 
-    mojo help
+  % mojo --help
 
 =head1 DESCRIPTION
 
@@ -0,0 +1,79 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+
+use File::Basename 'dirname';
+use File::Spec;
+
+use lib join '/', File::Spec->splitdir(dirname(__FILE__)), 'lib';
+use lib join '/', File::Spec->splitdir(dirname(__FILE__)), '..', 'lib';
+
+# Check if Mojo is installed
+eval 'use Mojo::Server::Morbo';
+die <<EOF if $@;
+It looks like you don't have the Mojolicious Framework installed.
+Please visit http://mojolicio.us for detailed installation instructions.
+
+EOF
+
+use Getopt::Long 'GetOptions';
+
+# "Welcome to 'Entertainment And Earth Invasion Tonite'.
+#  Across the galaxy my people are completing the mighty space fleet that
+#  will exterminate the human race!
+#  But first, this news from Tinseltown."
+my $morbo = Mojo::Server::Morbo->new;
+my ($help, @listen, @watch);
+GetOptions(
+  help => sub { $help = 1 },
+  'listen=s' => \@listen,
+  'watch=s'  => \@watch
+);
+$help = 1 unless my $app = shift;
+
+# Usage
+die <<"EOF" if $help;
+usage: $0 [OPTIONS] [APPLICATION]
+
+  morbo script/myapp
+  morbo myapp.pl
+
+These options are available:
+  --help                     Show this message.
+  --listen <location>        Set one or more locations you want to listen on,
+                             defaults to http://*:3000.
+  --watch <directory/file>   Set one or more directories and files to watch
+                             for changes, defaults to the application script
+                             as well as the "lib" and "templates" directories
+                             in the current working directory.
+EOF
+
+# "With Halley's Comet out of ice, Earth is experiencing a sudden case of
+#  global warming.
+#  Morbo is pleased but sticky."
+$morbo->listen(\@listen) if @listen;
+$morbo->watch(\@watch)   if @watch;
+$morbo->run($app);
+
+__END__
+
+=head1 NAME
+
+morbo - Morbo HTTP 1.1 And WebSocket Development Server
+
+=head1 SYNOPSIS
+
+  % morbo --help
+  % morbo myapp.pl
+
+=head1 DESCRIPTION
+
+Start L<Mojolicious> and L<Mojolicious::Lite> applications with the
+L<Mojo::Server::Morbo> web server.
+
+=head1 SEE ALSO
+
+L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicio.us>.
+
+=cut
@@ -12,7 +12,7 @@ use Test::More;
 
 plan skip_all => 'Perl 5.10 or Digest::SHA required for this test!'
   unless eval { require Digest::SHA; 1 };
-plan tests => 106;
+plan tests => 112;
 
 use_ok 'Mojo::Util',       'md5_bytes';
 use_ok 'Mojo::ByteStream', 'b';
@@ -37,6 +37,17 @@ is $stream->decamelize, 'foo_b_b', 'right decamelized result';
 $stream = b('Foo::BB');
 is $stream->decamelize, 'foo-b_b', 'right decamelized result';
 
+# camelize/decamelize roundtrip
+my $original = 'MyApp::Controller::FooBAR';
+$stream = b($original);
+my $result = $stream->decamelize->to_string;
+is "$stream", $result, 'stringified successfully';
+isnt $result, $original, 'decamelized result is different';
+is $stream->camelize,   $original, 'successful roundtrip';
+is $stream->decamelize, $result,   'right decamelized result';
+isnt "$stream", $original, 'decamelized result is different';
+is $stream->camelize, $original, 'successful roundtrip again';
+
 # b64_encode
 $stream = b('foobar$%^&3217');
 is $stream->b64_encode, "Zm9vYmFyJCVeJjMyMTc=\n",
@@ -98,8 +109,8 @@ $stream = b('"foo 23 \"bar"');
 is $stream->unquote, 'foo 23 "bar', 'right unquoted result';
 
 # md5_bytes
-my $original = 'foo bar baz ♥';
-my $copy     = $original;
+$original = 'foo bar baz ♥';
+my $copy = $original;
 $stream = b($copy);
 is unpack('H*', $stream->md5_bytes), "a740aeb6e066f158cbf19fd92e890d2d",
   'right binary md5 checksum';
@@ -130,7 +141,7 @@ $stream = b('0');
 is $stream->size,      1,   'size is 1';
 is $stream->to_string, '0', 'right content';
 
-# hmac_md5_sum (RFC2202)
+# hmac_md5_sum (RFC 2202)
 is b("Hi There")->hmac_md5_sum(chr(0x0b) x 16),
   '9294727a3638bb1c13f48ef8158bfc9d', 'right hmac md5 checksum';
 is b("what do ya want for nothing?")->hmac_md5_sum("Jefe"),
@@ -151,7 +162,7 @@ is b(
   ->hmac_md5_sum(chr(0xaa) x 80), '6f630fad67cda0ee1fb1f562db3aa53e',
   'right hmac md5 checksum';
 
-# hmac_sha1_sum (RFC2202)
+# hmac_sha1_sum (RFC 2202)
 is b("Hi There")->hmac_sha1_sum(chr(0x0b) x 20),
   'b617318655057264e28bc0b6fb378c8ef146be00', 'right hmac sha1 checksum';
 is b("what do ya want for nothing?")->hmac_sha1_sum("Jefe"),
@@ -200,8 +211,8 @@ is "$stream", 'foobar&lt;baz&gt;&amp;&quot;&OElig;',
 
 # utf8 html_unescape
 $stream =
-  b('foobar&lt;baz&gt;&#x26;&#34;&OElig;')->decode('UTF-8')->html_unescape;
-is "$stream", "foobar<baz>&\"\x{152}", 'right html unescaped result';
+  b('foo&lt;baz&gt;&#x26;&#34;&OElig;&Foo;')->decode('UTF-8')->html_unescape;
+is "$stream", "foo<baz>&\"\x{152}&Foo;", 'right html unescaped result';
 
 # html_escape (path)
 $stream =
@@ -3,7 +3,11 @@
 use strict;
 use warnings;
 
-use Test::More tests => 7;
+use Test::More tests => 17;
+
+use Cwd 'getcwd';
+use File::Spec;
+use File::Temp;
 
 # "My cat's breath smells like cat food."
 use_ok 'Mojo::Command';
@@ -36,3 +40,45 @@ is $command->get_data('template4', 'Example::Package::Windows'),
 is_deeply [sort keys %{$command->get_all_data('Example::Package::Windows')}],
   [qw/template3 template4/], 'right DATA files';
 close $data;
+
+# Class to file and path
+is $command->class_to_file('Foo::Bar'), 'foo_bar',    'right file';
+is $command->class_to_path('Foo::Bar'), 'Foo/Bar.pm', 'right path';
+
+# Environment detection
+{
+  local $ENV{PLACK_ENV} = 'production';
+  is $command->detect, 'psgi', 'right environment';
+}
+{
+  local $ENV{PATH_INFO} = '/test';
+  is $command->detect, 'cgi', 'right environment';
+}
+{
+  local $ENV{GATEWAY_INTERFACE} = 'CGI/1.1';
+  is $command->detect, 'cgi', 'right environment';
+}
+{
+  local %ENV = ();
+  is $command->detect, 'fastcgi', 'right environment';
+}
+
+# Generating files
+my $dir = File::Temp::tempdir(CLEANUP => 1);
+my $cwd = getcwd;
+chdir $dir;
+$command->create_rel_dir('foo/bar');
+is -d File::Spec->catdir($dir, qw/foo bar/), 1, 'directory exists';
+my $template = "@@ foo_bar\njust <%= 'works' %>!\n";
+open $data, '<', \$template;
+no strict 'refs';
+*{"Mojo::Command::DATA"} = $data;
+$command->render_to_rel_file('foo_bar', 'bar/baz.txt');
+open my $txt, '<', $command->rel_file('bar/baz.txt');
+is join('', <$txt>), "just works!\n", 'right result';
+$command->chmod_rel_file('bar/baz.txt', 700);
+is -e $command->rel_file('bar/baz.txt'), 1, 'file is executable';
+$command->write_rel_file('123.xml', "seems\nto\nwork");
+open my $xml, '<', $command->rel_file('123.xml');
+is join('', <$xml>), "seems\nto\nwork", 'right result';
+chdir $cwd;
@@ -3,7 +3,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 30;
+use Test::More tests => 34;
 
 # "Hello, my name is Mr. Burns. I believe you have a letter for me.
 #  Okay Mr. Burns, what’s your first name.
@@ -23,6 +23,14 @@ $jar->add(
     value  => 'bar'
   )
 );
+$jar->add(
+  Mojo::Cookie::Response->new(
+    domain => '.kraih.com',
+    path   => '/',
+    name   => 'just',
+    value  => 'works'
+  )
+);
 my @cookies = $jar->find(Mojo::URL->new('http://kraih.com/foo'));
 is $cookies[0]->name,  'foo', 'right name';
 is $cookies[0]->value, 'bar', 'right value';
@@ -52,8 +60,8 @@ my $expired = Mojo::Cookie::Response->new(
 $expired->expires(time - 1);
 $jar->add($expired);
 @cookies = $jar->find(Mojo::URL->new('http://labs.kraih.com/foo'));
-is $cookies[0]->name,  'foo', 'right name';
-is $cookies[0]->value, 'bar', 'right value';
+is $cookies[0]->name,  'just',  'right name';
+is $cookies[0]->value, 'works', 'right value';
 is $cookies[1], undef, 'no second cookie';
 
 # Multiple cookies
@@ -67,10 +75,10 @@ $jar->add(
   )
 );
 @cookies = $jar->find(Mojo::URL->new('http://labs.kraih.com/foo'));
-is $cookies[0]->name,  'baz', 'right name';
-is $cookies[0]->value, '23',  'right value';
-is $cookies[1]->name,  'foo', 'right name';
-is $cookies[1]->value, 'bar', 'right value';
+is $cookies[0]->name,  'baz',   'right name';
+is $cookies[0]->value, '23',    'right value';
+is $cookies[1]->name,  'just',  'right name';
+is $cookies[1]->value, 'works', 'right value';
 is $cookies[2], undef, 'no third cookie';
 
 # Multiple cookies with leading dot
@@ -83,11 +91,13 @@ $jar->add(
   )
 );
 @cookies = $jar->find(Mojo::URL->new('http://labs.kraih.com/fo'));
-is $cookies[0]->name,  'baz',  'right name';
-is $cookies[0]->value, '23',   'right value';
-is $cookies[1]->name,  'this', 'right name';
-is $cookies[1]->value, 'that', 'right value';
-is $cookies[2], undef, 'no third cookie';
+is $cookies[0]->name,  'baz',   'right name';
+is $cookies[0]->value, '23',    'right value';
+is $cookies[1]->name,  'just',  'right name';
+is $cookies[1]->value, 'works', 'right value';
+is $cookies[2]->name,  'this',  'right name';
+is $cookies[2]->value, 'that',  'right value';
+is $cookies[3], undef, 'no fourth cookie';
 
 # Replace cookie
 $jar = Mojo::CookieJar->new;
@@ -126,6 +136,7 @@ $jar->add(
 is $cookies[0], undef, 'no cookie for port 80';
 @cookies = $jar->find(Mojo::URL->new('http://kraih.com:88/foo'));
 is $cookies[0]->value, 'bar', 'cookie for port 88';
+is $cookies[1], undef, 'no second cookie';
 
 # Switch between secure and normal cookies
 $jar = Mojo::CookieJar->new;
@@ -154,3 +165,4 @@ $jar->add(
 is $cookies[0]->value, 'bar', 'right value';
 @cookies = $jar->find(Mojo::URL->new('https://kraih.com/foo'));
 is $cookies[0]->value, 'bar', 'right value';
+is $cookies[1], undef, 'no second cookie';
@@ -8,11 +8,11 @@ use Test::More tests => 10;
 # "Can't we have one meeting that doesn't end with digging up a corpse?"
 use_ok 'Mojo::Date';
 
-# RFC822/1123
+# RFC 822/1123
 my $date = Mojo::Date->new('Sun, 06 Nov 1994 08:49:37 GMT');
 is $date->epoch, 784111777, 'right epoch value';
 
-# RFC850/1036
+# RFC 850/1036
 is $date->parse('Sunday, 06-Nov-94 08:49:37 GMT')->epoch,
   784111777, 'right epoch value';
 
@@ -5,7 +5,7 @@ use warnings;
 
 use utf8;
 
-use Test::More tests => 591;
+use Test::More tests => 597;
 
 # "Homer gave me a kidney: it wasn't his, I didn't need it,
 #  and it came postage due- but I appreciated the gesture!"
@@ -1309,6 +1309,25 @@ is $dom->find('body > ul > li > p')->[2]->text, '',           'no text';
 is $dom->find('body > ul > li')->[2]->all_text, 'Test 3 2 1', 'right text';
 is $dom->find('body > ul > li > p')->[2]->all_text, '', 'no text';
 
+# Advanced whitespace trimming (punctuation)
+$dom = Mojo::DOM->new->parse(<<EOF);
+<html>
+  <head>
+    <title>Real World!</title>
+  <body>
+    <div>foo <strong>bar</strong>.</div>
+    <div>foo<strong>, bar</strong>baz<strong>; yada</strong>.</div>
+    <div>foo<strong>: bar</strong>baz<strong>? yada</strong>!</div>
+EOF
+is $dom->find('html > head > title')->[0]->text, 'Real World!', 'right text';
+is $dom->find('body > div')->[0]->all_text,      'foo bar.',    'right text';
+is $dom->find('body > div')->[1]->all_text, 'foo, bar baz; yada.',
+  'right text';
+is $dom->find('body > div')->[1]->text, 'foo baz.', 'right text';
+is $dom->find('body > div')->[2]->all_text, 'foo: bar baz? yada!',
+  'right text';
+is $dom->find('body > div')->[2]->text, 'foo baz!', 'right text';
+
 # Real world JavaScript and CSS
 $dom = Mojo::DOM->new->parse(<<EOF);
 <html>
@@ -8,7 +8,6 @@ BEGIN { $ENV{MOJO_NO_IPV6} = $ENV{MOJO_POLL} = 1 }
 
 use Test::More;
 
-# "I ate the blue ones... they taste like burning."
 use File::Spec;
 use File::Temp;
 use FindBin;
@@ -22,8 +21,7 @@ plan skip_all => 'set TEST_HYPNOTOAD to enable this test (developer only!)'
   unless $ENV{TEST_HYPNOTOAD};
 plan tests => 40;
 
-# "Daddy, I'm scared. Too scared to even wet my pants.
-#  Just relax and it'll come, son."
+# "I ate the blue ones... they taste like burning."
 use_ok 'Mojo::Server::Hypnotoad';
 
 # Config
@@ -118,7 +118,7 @@ ok $found, 'found MX records';
 # Resolve A record and perform PTR roundtrip
 my ($a1, $ptr, $a2);
 $loop->resolve(
-  'perl.org',
+  'mojolicio.us',
   'A',
   sub {
     my ($self, $records) = @_;
@@ -3,7 +3,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 44;
+use Test::More tests => 34;
 
 use FindBin;
 use lib "$FindBin::Bin/lib";
@@ -68,30 +68,3 @@ ok !!LoaderTest::C->can('new'), 'loaded successfully';
 
 # Class does not exist
 ok $loader->load('LoaderTest'), 'nothing to load';
-
-# Reload
-my $file = IO::File->new;
-my $dir  = File::Temp::tempdir(CLEANUP => 1);
-my $path = File::Spec->catfile($dir, 'MojoTestReloader.pm');
-$file->open("> $path");
-$file->syswrite(
-  "package MojoTestReloader;\nsub test1 { 23 }\nsub test3 { 32 }\n1;");
-$file->close;
-push @INC, $dir;
-require MojoTestReloader;
-ok my $t1 = MojoTestReloader->can('test1'), 'loaded successfully';
-ok !MojoTestReloader->can('test2'), 'package is clean';
-is $t1->(), 23, 'right result';
-ok my $t3 = MojoTestReloader->can('test3'), 'loaded successfully';
-is $t3->(), 32, 'right result';
-sleep 2;
-$file->open("> $path");
-$file->syswrite(
-  "package MojoTestReloader;\nsub test2 { 26 }\nsub test3 { 62 }\n1;");
-$file->close;
-Mojo::Loader->reload;
-ok my $t2 = MojoTestReloader->can('test2'), 'loaded successfully';
-ok !MojoTestReloader->can('test1'), 'package is clean';
-is $t2->(), 26, 'right result';
-ok $t3 = MojoTestReloader->can('test3'), 'loaded successfully';
-is $t3->(), 62, 'right result';
@@ -147,7 +147,7 @@ is $req->leftovers, "GET / HTTP/1.1\x0d\x0a\x0d\x0a",
   'second request in leftovers';
 
 # Parse HTTP 1.1 start line, no headers and body with leading CRLFs
-# (SHOULD be ignored, RFC2616, Section 4.1)
+# (SHOULD be ignored, RFC 2616, Section 4.1)
 $req = Mojo::Message::Request->new;
 $req->parse("\x0d\x0aGET / HTTP/1.1\x0d\x0a\x0d\x0a");
 ok $req->is_done, 'request is done';
@@ -1529,7 +1529,7 @@ is $req->version, '1.0', 'right version';
 is $req->at_least_version('1.0'), 1,     'at least version 1.0';
 is $req->at_least_version('1.2'), undef, 'not version 1.2';
 is $req->body, 'hello=world', 'right content';
-is_deeply $req->param('hello'), 'world', 'right paramaters';
+is_deeply $req->param('hello'), 'world', 'right parameters';
 is $req->url->to_abs->to_string, 'http://localhost/test/index.cgi',
   'right absolute URL';
 
@@ -1769,7 +1769,7 @@ is $res2->cookie('baz')->value, 'yada',     'right value';
 is $res2->cookie('bar')->path,  '/test/23', 'right path';
 is $res2->cookie('bar')->value, 'baz',      'right value';
 
-# Build response with callback (make sure its called)
+# Build response with callback (make sure it's called)
 $res = Mojo::Message::Response->new;
 $res->code(200);
 $res->headers->content_length(10);
@@ -0,0 +1,167 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+
+# Disable IPv6, epoll and kqueue
+BEGIN { $ENV{MOJO_NO_IPV6} = $ENV{MOJO_POLL} = 1 }
+
+use Test::More;
+
+use FindBin;
+use IO::Socket::INET;
+use Mojo::IOLoop;
+use Mojo::Transaction::HTTP;
+use Mojo::UserAgent;
+
+plan skip_all => 'set TEST_MORBO to enable this test (developer only!)'
+  unless $ENV{TEST_MORBO};
+plan tests => 40;
+
+# "Morbo wishes these stalwart nomads peace among the Dutch tulips.
+#  At least all those windmills will keep them cool.
+#  WINDMILLS DO NOT WORK THAT WAY! GOODNIGHT!"
+use_ok 'Mojo::Server::Morbo';
+
+# Start
+my $port   = Mojo::IOLoop->generate_port;
+my $prefix = "$FindBin::Bin/../../script";
+my $pid    = open my $server, '-|', $^X, "$prefix/morbo", '--listen',
+  "http://*:$port", "$prefix/mojo";
+sleep 1
+  while !IO::Socket::INET->new(
+  Proto    => 'tcp',
+  PeerAddr => 'localhost',
+  PeerPort => $port
+  );
+
+my $ua = Mojo::UserAgent->new;
+
+# Single request without keep alive
+my $tx = Mojo::Transaction::HTTP->new;
+$tx->req->method('GET');
+$tx->req->url->parse("http://127.0.0.1:$port/0/");
+$tx->req->headers->connection('close');
+$ua->start($tx);
+ok $tx->is_done, 'transaction is done';
+is $tx->res->code, 200, 'right status';
+like $tx->res->headers->connection, qr/close/i, 'right "Connection" header';
+like $tx->res->body, qr/Mojo/, 'right content';
+
+# Multiple requests
+$tx = Mojo::Transaction::HTTP->new;
+$tx->req->method('GET');
+$tx->req->url->parse("http://127.0.0.1:$port/1/");
+my $tx2 = Mojo::Transaction::HTTP->new;
+$tx2->req->method('GET');
+$tx2->req->url->parse("http://127.0.0.1:$port/2/");
+$tx2->req->headers->expect('fun');
+$tx2->req->body('foo bar baz');
+my $tx3 = Mojo::Transaction::HTTP->new;
+$tx3->req->method('GET');
+$tx3->req->url->parse("http://127.0.0.1:$port/3/");
+my $tx4 = Mojo::Transaction::HTTP->new;
+$tx4->req->method('GET');
+$tx4->req->url->parse("http://127.0.0.1:$port/4/");
+$ua->start($tx);
+$ua->start($tx2);
+$ua->start($tx3);
+$ua->start($tx4);
+ok $tx->is_done,  'transaction is done';
+ok $tx2->is_done, 'transaction is done';
+ok $tx3->is_done, 'transaction is done';
+ok $tx4->is_done, 'transaction is done';
+is $tx->res->code,  200, 'right status';
+is $tx2->res->code, 200, 'right status';
+is $tx3->res->code, 200, 'right status';
+is $tx4->res->code, 200, 'right status';
+like $tx2->res->content->asset->slurp, qr/Mojo/, 'right content';
+
+# Request
+$tx = Mojo::Transaction::HTTP->new;
+$tx->req->method('GET');
+$tx->req->url->parse("http://127.0.0.1:$port/5/");
+$tx->req->headers->expect('fun');
+$tx->req->body('Hello Mojo!');
+$ua->start($tx);
+is $tx->res->code, 200, 'right status';
+like $tx->res->headers->connection, qr/Keep-Alive/i,
+  'right "Connection" header';
+like $tx->res->body, qr/Mojo/, 'right content';
+
+# Second keep alive request
+$tx = Mojo::Transaction::HTTP->new;
+$tx->req->method('GET');
+$tx->req->url->parse("http://127.0.0.1:$port/6/");
+$ua->start($tx);
+is $tx->res->code, 200, 'right status';
+is $tx->kept_alive, 1, 'connection was alive';
+like $tx->res->headers->connection,
+  qr/Keep-Alive/i, 'right "Connection" header';
+like $tx->res->body, qr/Mojo/, 'right content';
+
+# Third keep alive request
+$tx = Mojo::Transaction::HTTP->new;
+$tx->req->method('GET');
+$tx->req->url->parse("http://127.0.0.1:$port/7/");
+$ua->start($tx);
+is $tx->res->code, 200, 'right status';
+is $tx->kept_alive, 1, 'connection was kept alive';
+like $tx->res->headers->connection,
+  qr/Keep-Alive/i, 'right "Connection" header';
+like $tx->res->body, qr/Mojo/, 'right content';
+
+# Multiple requests
+$tx = Mojo::Transaction::HTTP->new;
+$tx->req->method('GET');
+$tx->req->url->parse("http://127.0.0.1:$port/8/");
+$tx2 = Mojo::Transaction::HTTP->new;
+$tx2->req->method('GET');
+$tx2->req->url->parse("http://127.0.0.1:$port/9/");
+$ua->start($tx);
+$ua->start($tx2);
+ok $tx->is_done,  'transaction is done';
+ok $tx2->is_done, 'transaction is done';
+is $tx->res->code,  200, 'right status';
+is $tx2->res->code, 200, 'right status';
+like $tx2->res->content->asset->slurp, qr/Mojo/, 'right content';
+
+# Multiple requests with a chunked response
+$tx = Mojo::Transaction::HTTP->new;
+$tx->req->method('GET');
+$tx->req->url->parse("http://127.0.0.1:$port/10/");
+$tx2 = Mojo::Transaction::HTTP->new;
+$tx2->req->method('GET');
+$tx2->req->url->parse("http://127.0.0.1:$port/11/");
+$tx2->req->headers->expect('fun');
+$tx2->req->body('foo bar baz');
+$tx3 = Mojo::Transaction::HTTP->new;
+$tx3->req->method('GET');
+$tx3->req->url->parse(
+  "http://127.0.0.1:$port/diag/chunked_params?a=foo&b=12");
+$tx4 = Mojo::Transaction::HTTP->new;
+$tx4->req->method('GET');
+$tx4->req->url->parse("http://127.0.0.1:$port/13/");
+$ua->start($tx);
+$ua->start($tx2);
+$ua->start($tx3);
+$ua->start($tx4);
+ok $tx->is_done,  'transaction is done';
+ok $tx2->is_done, 'transaction is done';
+ok $tx3->is_done, 'transaction is done';
+ok $tx4->is_done, 'transaction is done';
+is $tx->res->code,  200, 'right status';
+is $tx2->res->code, 200, 'right status';
+is $tx3->res->code, 200, 'right status';
+is $tx4->res->code, 200, 'right status';
+like $tx2->res->content->asset->slurp, qr/Mojo/, 'right content';
+is $tx3->res->content->asset->slurp,   'foo12',  'right content';
+
+# Stop
+kill 'INT', $pid;
+sleep 1
+  while IO::Socket::INET->new(
+  Proto    => 'tcp',
+  PeerAddr => 'localhost',
+  PeerPort => $port
+  );
@@ -5,7 +5,7 @@ use warnings;
 
 use utf8;
 
-use Test::More tests => 44;
+use Test::More tests => 62;
 
 # "Now that's a wave of destruction that's easy on the eyes."
 use_ok 'Mojo::Parameters';
@@ -16,6 +16,8 @@ my $params2 = Mojo::Parameters->new('x', 1, 'y', 2);
 is $params->pair_separator, '&',                 'right pair separator';
 is $params->to_string,      'foo=b%3Bar&baz=23', 'right format';
 is $params2->to_string,     'x=1&y=2',           'right format';
+is $params->to_string,      'foo=b%3Bar&baz=23', 'right format';
+is_deeply $params->params, ['foo', 'b;ar', 'baz', 23], 'right structure';
 $params->pair_separator(';');
 is $params->to_string, 'foo=b%3Bar;baz=23', 'right format';
 is "$params", 'foo=b%3Bar;baz=23', 'right format';
@@ -72,6 +74,20 @@ $params = Mojo::Parameters->new($params->to_string);
 is_deeply $params->param('foo'), 0, 'right structure';
 is $params->to_string, 'foo=0', 'right format';
 
+# Semicolon
+$params = Mojo::Parameters->new('foo=bar;baz');
+is $params->pair_separator, '&',           'right pair separator';
+is $params->to_string,      'foo=bar;baz', 'right format';
+is_deeply $params->params, [foo => 'bar', baz => ''], 'right structure';
+is_deeply $params->to_hash, {foo => 'bar', baz => ''}, 'right structure';
+is $params->pair_separator, ';',            'right pair separator';
+is $params->to_string,      'foo=bar;baz=', 'right format';
+$params = Mojo::Parameters->new('foo=bar%3Bbaz');
+is $params->pair_separator, '&', 'right pair separator';
+is_deeply $params->params, [foo => 'bar;baz'], 'right structure';
+is_deeply $params->to_hash, {foo => 'bar;baz'}, 'right structure';
+is $params->to_string, 'foo=bar%3Bbaz', 'right format';
+
 # Reconstruction
 $params = Mojo::Parameters->new('foo=bar&baz=23');
 is "$params", 'foo=bar&baz=23', 'right format';
@@ -89,6 +105,9 @@ $params->remove('c');
 is $params->to_string, "=c&=", 'right format';
 $params->remove(undef);
 ok !$params->to_string, 'empty';
+$params->parse('');
+ok !$params->to_string, 'empty';
+is_deeply $params->to_hash, {}, 'right structure';
 
 # +
 $params = Mojo::Parameters->new('foo=%2B');
@@ -101,6 +120,11 @@ is_deeply $params->to_hash, {foo => '+'}, 'right structure';
 $params->append('1 2', '3+3');
 is $params->param('1 2'), '3+3', 'right value';
 is_deeply $params->to_hash, {foo => '+', '1 2' => '3+3'}, 'right structure';
+$params = Mojo::Parameters->new('a=works+too');
+is "$params", 'a=works+too', 'right format';
+is_deeply $params->to_hash, {a => 'works too'}, 'right structure';
+is $params->param('a'), 'works too', 'right value';
+is "$params", 'a=works+too', 'right format';
 
 # Array values
 $params = Mojo::Parameters->new;
@@ -174,7 +174,7 @@ $output = $mt->render(<<'EOF');
 EOF
 is $output, "<html>\n\n", 'expression block';
 
-# Escaped expression block (extra whitespace)
+# Escaped expression block (passed through with extra whitespace)
 $mt     = Mojo::Template->new;
 $output = $mt->render(<<'EOF');
 <% my $block =  begin %>
@@ -182,9 +182,10 @@ $output = $mt->render(<<'EOF');
 <% end  %>
 <%== $block->() %>
 EOF
-is $output, "\n\n&lt;html&gt;\n\n", 'escaped expression block';
+is $output, "\n\n<html>\n\n", 'escaped expression block';
 
-# Escaped expression block (perl lines and extra whitespace)
+# Escaped expression block
+# (passed through with perl lines and extra whitespace)
 $mt     = Mojo::Template->new;
 $output = $mt->render(<<'EOF');
 % my $block =  begin
@@ -192,9 +193,10 @@ $output = $mt->render(<<'EOF');
 <% end  %>
 <%== $block->() %>
 EOF
-is $output, "\n&lt;html&gt;\n\n", 'escaped expression block';
+is $output, "\n<html>\n\n", 'escaped expression block';
 
-# Escaped expression block (indented perl lines and extra whitespace)
+# Escaped expression block
+# (passed through with indented perl lines and extra whitespace)
 $mt     = Mojo::Template->new;
 $output = $mt->render(<<'EOF');
  % my $block =  begin
@@ -202,9 +204,9 @@ $output = $mt->render(<<'EOF');
    % end
 <%== $block->() %>
 EOF
-is $output, "&lt;html&gt;\n\n", 'escaped expression block';
+is $output, "<html>\n\n", 'escaped expression block';
 
-# Captured escaped expression block (extra whitespace)
+# Captured escaped expression block (passed through with extra whitespace)
 $mt     = Mojo::Template->new;
 $output = $mt->render(<<'EOF');
 <%== my $result = capture begin  =%>
@@ -212,9 +214,10 @@ $output = $mt->render(<<'EOF');
 <%  end =%>
 <%= $result =%>
 EOF
-is $output, '&lt;html&gt;<html>', 'captured escaped expression block';
+is $output, '<html><html>', 'captured escaped expression block';
 
-# Captured escaped expression block (perl lines and extra whitespace)
+# Captured escaped expression block
+# (passed through with perl lines and extra whitespace)
 $mt     = Mojo::Template->new;
 $output = $mt->render(<<'EOF');
 %== my $result = capture  begin
@@ -224,12 +227,13 @@ $output = $mt->render(<<'EOF');
 EOF
 is $output, <<EOF, 'captured escaped expression block';
 
-&lt;html&gt;
+<html>
 
 <html>
 EOF
 
-# Captured escaped expression block (indented perl lines and extra whitespace)
+# Captured escaped expression block
+# (passed through with indented perl lines and extra whitespace)
 $mt     = Mojo::Template->new;
 $output = $mt->render(<<'EOF');
 %== my $result = capture  begin
@@ -239,12 +243,12 @@ $output = $mt->render(<<'EOF');
 EOF
 is $output, <<EOF, 'captured escaped expression block';
 
-&lt;html&gt;
+<html>
 
 <html>
 EOF
 
-# Capture lines (extra whitespace)
+# Capture lines (passed through with extra whitespace)
 $mt     = Mojo::Template->new;
 $output = $mt->render(<<'EOF');
 <% my $result = escape capture begin                  %>
@@ -252,46 +256,46 @@ $output = $mt->render(<<'EOF');
 <%                        end %>
 %= $result
 EOF
-is $output, "\n\n&lt;html&gt;\n\n", 'captured lines';
+is $output, "\n\n<html>\n\n", 'captured lines';
 
-# Capture tags
+# Capture tags (passed through)
 $mt     = Mojo::Template->new;
 $output = $mt->render(<<'EOF');
 <% my $result = escape capture begin %><html><% end %><%= $result %>
 EOF
-is $output, "&lt;html&gt;\n", 'capture tags';
+is $output, "<html>\n", 'capture tags';
 
-# Capture tags (alternative)
+# Capture tags (passed through alternative)
 $mt     = Mojo::Template->new;
 $output = $mt->render(<<'EOF');
 <% my $result = escape capture begin %><html><% end %><%= $result %>
 EOF
-is $output, "&lt;html&gt;\n", 'capture tags';
+is $output, "<html>\n", 'capture tags';
 
-# Capture tags with appended code
+# Capture tags with appended code (passed through)
 $mt     = Mojo::Template->new;
 $output = $mt->render(<<'EOF');
 <% my $result = escape( capture begin %><html><% end ); %><%= $result %>
 EOF
-is $output, "&lt;html&gt;\n", 'capture tags with appended code';
+is $output, "<html>\n", 'capture tags with appended code';
 
-# Capture tags with appended code (alternative)
+# Capture tags with appended code (passed through alternative)
 $mt     = Mojo::Template->new;
 $output = $mt->render(<<'EOF');
 <% my $result = escape( capture begin %><html><% end ); %><%= $result %>
 EOF
-is $output, "&lt;html&gt;\n", 'capture tags with appended code';
+is $output, "<html>\n", 'capture tags with appended code';
 
-# Nested capture tags
+# Nested capture tags (passed through)
 $mt     = Mojo::Template->new;
 $output = $mt->render(<<'EOF');
 <% my $result = capture
   begin %><%= escape capture begin %><html><% end
   %><% end %><%= $result %>
 EOF
-is $output, "&lt;html&gt;\n", 'nested capture tags';
+is $output, "<html>\n", 'nested capture tags';
 
-# Nested capture tags (alternative)
+# Nested capture tags (passed through alternative)
 $mt     = Mojo::Template->new;
 $output = $mt->render(<<'EOF');
 <% my $result = capture begin =%>
@@ -301,7 +305,7 @@ $output = $mt->render(<<'EOF');
 <% end =%>
 <%= $result =%>
 EOF
-is $output, '&lt;html&gt;', 'nested capture tags';
+is $output, '<html>', 'nested capture tags';
 
 # Advanced capturing (extra whitespace)
 $mt     = Mojo::Template->new;
@@ -525,13 +529,13 @@ $output = $mt->render(<<'EOF');
 %= __PACKAGE__
 %= foo
 EOF
-is $output, "Mojo::Template::Context\nworks!\n", 'right result';
+is $output, "Mojo::Template::SandBox\nworks!\n", 'right result';
 $output = $mt->render(<<'EOF');
 % BEGIN { MyTemplateExporter->import }
 %= __PACKAGE__
 %= foo
 EOF
-is $output, "Mojo::Template::Context\nworks!\n", 'right result';
+is $output, "Mojo::Template::SandBox\nworks!\n", 'right result';
 
 # Unusable error message (stacktrace required)
 $mt     = Mojo::Template->new;
@@ -5,7 +5,7 @@ use warnings;
 
 use utf8;
 
-use Test::More tests => 321;
+use Test::More tests => 322;
 
 # "I don't want you driving around in a car you built yourself.
 #  You can sit there complaining, or you can knit me some seat belts."
@@ -59,22 +59,23 @@ is "$url", 'http://sri:foobar@kraih.com:8080?monkey=bar&foo=bar#23',
 $url->query('foo');
 is "$url", 'http://sri:foobar@kraih.com:8080?foo#23', 'right format';
 $url->query('foo=bar');
-is "$url", 'http://sri:foobar@kraih.com:8080?foo%3Dbar#23', 'right format';
+is "$url", 'http://sri:foobar@kraih.com:8080?foo=bar#23', 'right format';
 
 # Query string
 $url = Mojo::URL->new(
   'http://sri:foobar@kraih.com:8080?_monkeybiz%3B&_monkey;23#23');
-is $url->is_abs,   1,                              'is absolute';
-is $url->scheme,   'http',                         'right scheme';
-is $url->userinfo, 'sri:foobar',                   'right userinfo';
-is $url->host,     'kraih.com',                    'right host';
-is $url->port,     '8080',                         'right port';
-is $url->path,     '',                             'no path';
-is $url->query,    '_monkeybiz%3B%26_monkey%3B23', 'right query';
-is_deeply $url->query->params, ['_monkeybiz;&_monkey;23', undef],
+is $url->is_abs,   1,                          'is absolute';
+is $url->scheme,   'http',                     'right scheme';
+is $url->userinfo, 'sri:foobar',               'right userinfo';
+is $url->host,     'kraih.com',                'right host';
+is $url->port,     '8080',                     'right port';
+is $url->path,     '',                         'no path';
+is $url->query,    '_monkeybiz%3B&_monkey;23', 'right query';
+is_deeply $url->query->params, ['_monkeybiz;', '', '_monkey', '', 23, ''],
   'right structure';
+is $url->query, '_monkeybiz%3B=&_monkey=&23=', 'right query';
 is $url->fragment, '23', 'right fragment';
-is "$url", 'http://sri:foobar@kraih.com:8080?_monkeybiz%3B%26_monkey%3B23#23',
+is "$url", 'http://sri:foobar@kraih.com:8080?_monkeybiz%3B=&_monkey=&23=#23',
   'right format';
 
 # Relative
@@ -4,7 +4,10 @@ use strict;
 use warnings;
 
 # Disable IPv6, epoll and kqueue
-BEGIN { $ENV{MOJO_NO_IPV6} = $ENV{MOJO_POLL} = 1 }
+BEGIN {
+  $ENV{MOJO_NO_IPV6} = $ENV{MOJO_POLL} = 1;
+  $ENV{MOJO_MODE} = 'development';
+}
 
 use Test::More tests => 249;
 
@@ -24,9 +27,6 @@ use_ok 'MojoliciousTest';
 
 my $t = Test::Mojo->new(app => 'MojoliciousTest');
 
-my $backup = $ENV{MOJO_MODE} || '';
-$ENV{MOJO_MODE} = 'development';
-
 # Foo::fun
 my $url = $t->build_url;
 $url->path('/fun/time');
@@ -329,5 +329,3 @@ $t->get_ok('/foo/session')->status_is(200)
 # Mixed formats
 $t->get_ok('/rss.xml')->status_is(200)->content_type_is('application/rss+xml')
   ->content_like(qr/<\?xml version="1.0" encoding="UTF-8"\?><rss \/>/);
-
-$ENV{MOJO_MODE} = $backup;
@@ -93,7 +93,7 @@ my $tx = Mojo::Transaction::HTTP->new;
 $tx->req->method('GET');
 $tx->req->url->parse('/not_found');
 $c->tx($tx);
-is $d->dispatch($c), 1, 'dispatched';
+is $d->dispatch($c), undef, 'not dispatched';
 is_deeply $c->stash, {}, 'empty stash';
 ok !$c->render_called, 'nothing rendered';
 
@@ -104,7 +104,7 @@ $tx->req->method('POST');
 $tx->req->url->parse('/foo/hello');
 $c->tx($tx);
 $c->stash(test => 23);
-is $d->dispatch($c), undef, 'dispatched';
+is $d->dispatch($c), 1, 'dispatched';
 is $c->stash->{controller}, 'foo',   'right value';
 is $c->stash->{action},     'bar',   'right value';
 is $c->stash->{capture},    'hello', 'right value';
@@ -152,7 +152,7 @@ $tx = Mojo::Transaction::HTTP->new;
 $tx->req->method('GET');
 $tx->req->url->parse('/foo/hello%20there');
 $c->tx($tx);
-is $d->dispatch($c), undef, 'dispatched';
+is $d->dispatch($c), 1, 'dispatched';
 is $c->stash->{controller}, 'foo',         'right value';
 is $c->stash->{action},     'bar',         'right value';
 is $c->stash->{capture},    'hello there', 'right value';
@@ -168,7 +168,7 @@ $tx = Mojo::Transaction::HTTP->new;
 $tx->req->method('GET');
 $tx->req->url->parse('/foo/%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82');
 $c->tx($tx);
-is $d->dispatch($c), undef, 'dispatched';
+is $d->dispatch($c), 1, 'dispatched';
 is $c->stash->{controller}, 'foo',          'right value';
 is $c->stash->{action},     'bar',          'right value';
 is $c->stash->{capture},    'привет', 'right value';
@@ -3,10 +3,15 @@
 use strict;
 use warnings;
 
+use utf8;
+
 # Disable IPv6, epoll and kqueue
-BEGIN { $ENV{MOJO_NO_IPV6} = $ENV{MOJO_POLL} = 1 }
+BEGIN {
+  $ENV{MOJO_NO_IPV6} = $ENV{MOJO_POLL} = 1;
+  $ENV{MOJO_MODE} = 'testing';
+}
 
-use Test::More tests => 41;
+use Test::More tests => 113;
 
 use FindBin;
 use lib "$FindBin::Bin/lib";
@@ -32,8 +37,6 @@ get '/hello' => sub {
 package MyTestApp::Test1;
 use Mojolicious::Lite;
 
-use Mojo::IOLoop;
-
 # GET /yada (embedded)
 get '/yada' => sub {
   my $self = shift;
@@ -85,6 +88,17 @@ plugin 'PluginWithEmbeddedApp';
 
 app->routes->namespace('MyTestApp');
 
+# Mount full external application twice
+use FindBin;
+my $external = "$FindBin::Bin/external/myapp.pl";
+plugin mount => {'/x/1' => $external};
+plugin(mount => ('/x/♥' => $external))->to(message => 'works 2!');
+plugin mount => {'mojolicious.org' => $external};
+plugin mount => {'MOJOLICIO.US/'   => $external};
+plugin mount => {'*.kraih.com'     => $external};
+plugin(mount => ('*.foo-bar.de/♥/123' => $external))
+  ->to(message => 'works 3!');
+
 # GET /hello
 get '/hello' => 'works';
 
@@ -117,6 +131,8 @@ app->routes->route('/hello')->detour(TestApp::app())->to(name => 'embedded');
 # GET /just/* (external embedded app)
 get('/just' => {name => 'working'})->detour('EmbeddedTestApp');
 
+get '/host' => {text => 'main application!'};
+
 my $t = Test::Mojo->new;
 
 # GET /foo/bar (plugin app)
@@ -170,6 +186,97 @@ $t->get_ok('/third')->status_is(200)
 # GET /just/works (from external embedded app)
 $t->get_ok('/just/works')->status_is(200)->content_is("It is working!\n");
 
+# GET /x/1/ (full external application)
+$t->get_ok('/x/1/')->status_is(200)->content_is("works!\n\ntoo!works!!!\n");
+
+# GET /x/1/index.html (full external application)
+$t->get_ok('/x/1/index.html')->status_is(200)
+  ->content_is('External static file!');
+
+# GET /x/1/echo (full external application)
+$t->get_ok('/x/1/echo')->status_is(200)->content_is('echo: nothing!');
+
+# GET /x/1/stream (full external application)
+$t->get_ok('/x/1/stream')->status_is(200)->content_is('hello!');
+
+# GET /x/1/url/☃ (full external application)
+$t->get_ok('/x/1/url/☃')->status_is(200)
+  ->content_is('/x/1/url/%E2%98%83 -> /x/1/%E2%98%83/stream!');
+
+# GET /x/♥/ (full external application)
+$t->get_ok('/x/♥/')->status_is(200)->content_is("works!\n\ntoo!works!!!\n");
+
+# GET /x/♥/index.html (full external application)
+$t->get_ok('/x/♥/index.html')->status_is(200)
+  ->content_is('External static file!');
+
+# GET /x/♥/echo (full external application)
+$t->get_ok('/x/♥/echo')->status_is(200)->content_is('echo: works 2!');
+
+# GET /x/♥/stream (full external application)
+$t->get_ok('/x/♥/stream')->status_is(200)->content_is('hello!');
+
+# GET /x/♥/url/☃ (full external application)
+$t->get_ok('/x/♥/url/☃')->status_is(200)
+  ->content_is(
+  '/x/%E2%99%A5/url/%E2%98%83 -> /x/%E2%99%A5/%E2%98%83/stream!');
+
+# GET /host (main application)
+$t->get_ok('/host')->status_is(200)->content_is('main application!');
+
+# GET / (full external application with domain)
+$t->get_ok('/' => {Host => 'mojolicious.org'})->status_is(200)
+  ->content_is("works!\n\ntoo!works!!!\n");
+
+# GET /host (full external application with domain)
+$t->get_ok('/host' => {Host => 'mojolicious.org'})->status_is(200)
+  ->content_is('mojolicious.org');
+
+# GET / (full external application with domain)
+$t->get_ok('/' => {Host => 'mojolicio.us'})->status_is(200)
+  ->content_is("works!\n\ntoo!works!!!\n");
+
+# GET /host (full external application with domain)
+$t->get_ok('/host' => {Host => 'mojolicio.us'})->status_is(200)
+  ->content_is('mojolicio.us');
+
+# GET / (full external application with domain)
+$t->get_ok('/' => {Host => 'kraih.com'})->status_is(200)
+  ->content_is("works!\n\ntoo!works!!!\n");
+
+# GET /host (full external application with domain)
+$t->get_ok('/host' => {Host => 'KRaIH.CoM'})->status_is(200)
+  ->content_is('kraih.com');
+
+# GET /host (full external application with wildcard domain)
+$t->get_ok('/host' => {Host => 'www.kraih.com'})->status_is(200)
+  ->content_is('www.kraih.com');
+
+# GET /host (full external application with wildcard domain)
+$t->get_ok('/host' => {Host => 'foo.bar.kraih.com'})->status_is(200)
+  ->content_is('foo.bar.kraih.com');
+
+# GET /♥/123/host (full external application with a bit of everything)
+$t->get_ok('/♥/123/' => {Host => 'foo-bar.de'})->status_is(200)
+  ->content_is("works!\n\ntoo!works!!!\n");
+
+# GET /♥/123/host (full external application with a bit of everything)
+$t->get_ok('/♥/123/host' => {Host => 'foo-bar.de'})->status_is(200)
+  ->content_is('foo-bar.de');
+
+# GET /♥/123/echo (full external application with a bit of everything)
+$t->get_ok('/♥/123/echo' => {Host => 'foo-bar.de'})->status_is(200)
+  ->content_is('echo: works 3!');
+
+# GET /♥/123/host (full external application with a bit of everything)
+$t->get_ok('/♥/123/host' => {Host => 'www.foo-bar.de'})->status_is(200)
+  ->content_is('www.foo-bar.de');
+
+# GET /♥/123/echo (full external application with a bit of everything)
+$t->get_ok('/♥/123/echo' => {Host => 'www.foo-bar.de'})->status_is(200)
+  ->content_is('echo: works 3!');
+
 __DATA__
+
 @@ works.html.ep
 Hello from the main app!
@@ -4,13 +4,12 @@ use strict;
 use warnings;
 
 # Disable IPv6, epoll and kqueue
-BEGIN { $ENV{MOJO_NO_IPV6} = $ENV{MOJO_POLL} = 1 }
+BEGIN {
+  $ENV{MOJO_NO_IPV6} = $ENV{MOJO_POLL} = 1;
+  $ENV{MOJO_MODE} = 'development';
+}
 
-# Development
-my $backup;
-BEGIN { $backup = $ENV{MOJO_MODE} || ''; $ENV{MOJO_MODE} = 'development' }
-
-use Test::More tests => 28;
+use Test::More tests => 32;
 
 # "This calls for a party, baby.
 #  I'm ordering 100 kegs, 100 hookers and 100 Elvis impersonators that aren't
@@ -26,6 +25,9 @@ get '/dead_template';
 # GET /dead_included_template
 get '/dead_included_template';
 
+# GET /dead_template_with_layout
+get '/dead_template_with_layout';
+
 # GET /dead_action
 get '/dead_action' => sub { die 'dead action!' };
 
@@ -76,8 +78,12 @@ $t->get_ok('/dead_template')->status_is(500)->content_like(qr/1\./)
 $t->get_ok('/dead_included_template')->status_is(500)->content_like(qr/1\./)
   ->content_like(qr/dead\ template!/);
 
+# GET /dead_template_with_layout
+$t->get_ok('/dead_template_with_layout')->status_is(500)
+  ->content_like(qr/2\./)->content_like(qr/dead\ template\ with\ layout!/);
+
 # GET /dead_action
-$t->get_ok('/dead_action')->status_is(500)->content_like(qr/26\./)
+$t->get_ok('/dead_action')->status_is(500)->content_like(qr/32\./)
   ->content_like(qr/dead\ action!/);
 
 # GET /double_dead_action
@@ -90,9 +96,10 @@ $t->get_ok('/trapped')->status_is(200)->content_is('bar');
 # GET /trapped/too
 $t->get_ok('/trapped/too')->status_is(200)->content_is('works');
 
-$ENV{MOJO_MODE} = $backup;
-
 __DATA__
+@@ layouts/green.html.ep
+%= content
+
 @@ dead_template.html.ep
 % die 'dead template!';
 
@@ -100,3 +107,7 @@ __DATA__
 this
 %= include 'dead_template'
 works!
+
+@@ dead_template_with_layout.html.ep
+% layout 'green';
+% die 'dead template with layout!';
@@ -3,6 +3,8 @@
 use strict;
 use warnings;
 
+use utf8;
+
 # "Boy, who knew a cooler could also make a handy wang coffin?"
 use Mojolicious::Lite;
 
@@ -12,7 +14,38 @@ plugin 'config';
 # GET /
 get '/' => 'index';
 
+# GET /echo
+get '/echo' => sub {
+  my $self = shift;
+  $self->render_text('echo: ' . ($self->stash('message') || 'nothing!'));
+};
+
+# GET /stream
+get '/stream' => sub {
+  shift->write_chunk(
+    'he',
+    sub {
+      shift->write_chunk('ll', sub { shift->finish('o!') });
+    }
+  );
+};
+
+# GET /url/☃
+get '/url/☃' => sub {
+  my $self  = shift;
+  my $route = $self->url_for;
+  my $rel   = $self->url_for('/☃/stream');
+  $self->render_text("$route -> $rel!");
+};
+
+# GET /host
+get '/host' => sub {
+  my $self = shift;
+  $self->render(text => $self->url_for->base->host);
+};
+
 app->start;
 __DATA__
-@@ index.html.ep
-<%= $config->{just} . $config->{works} . stash('also') %>
+
+@@ menubar.html.ep
+<%= $config->{just} %>
@@ -0,0 +1,2 @@
+%= include 'menubar'
+<%= $config->{works} . stash('also') %>
\ No newline at end of file
@@ -12,7 +12,7 @@ BEGIN {
 }
 
 # "Who are you, and why should I care?"
-use Test::More tests => 6;
+use Test::More tests => 15;
 
 # "Of all the parasites I've had over the years,
 #  these worms are among the best."
@@ -23,8 +23,18 @@ use Test::Mojo;
 my $t = Test::Mojo->new;
 
 # GET /
-$t->get_ok('/')->status_is(200)->content_is("works!too!works!!!\n");
+$t->get_ok('/')->status_is(200)->content_is("works!\n\ntoo!works!!!\n");
 
 # GET /index.html
 $t->get_ok('/index.html')->status_is(200)
   ->content_is('External static file!');
+
+# GET /echo
+$t->get_ok('/echo')->status_is(200)->content_is('echo: nothing!');
+
+# GET /stream
+$t->get_ok('/stream')->status_is(200)->content_is('hello!');
+
+# GET /url/☃
+$t->get_ok('/url/☃')->status_is(200)
+  ->content_is('/url/%E2%98%83 -> /%E2%98%83/stream!');
@@ -14,7 +14,7 @@ sub this_one_dies { die "doh!\n" }
 
 sub this_one_might_die {
   die "double doh!\n" unless shift->req->headers->header('X-DoNotDie');
-  return 1;
+  1;
 }
 
 1;
@@ -41,7 +41,7 @@ sub stage1 {
 
   # Fail
   $self->render_text('Go away!');
-  return;
+  undef;
 }
 
 sub stage2 {
@@ -6,13 +6,12 @@ use warnings;
 use utf8;
 
 # Disable IPv6, epoll and kqueue
-BEGIN { $ENV{MOJO_NO_IPV6} = $ENV{MOJO_POLL} = 1 }
+BEGIN {
+  $ENV{MOJO_NO_IPV6} = $ENV{MOJO_POLL} = 1;
+  $ENV{MOJO_MODE} = 'development';
+}
 
-# Development
-my $backup;
-BEGIN { $backup = $ENV{MOJO_MODE} || ''; $ENV{MOJO_MODE} = 'development' }
-
-use Test::More tests => 792;
+use Test::More tests => 823;
 
 # Pollution
 123 =~ m/(\d+)/;
@@ -37,8 +36,10 @@ use Test::Mojo;
 # User agent
 my $ua = Mojo::UserAgent->new(ioloop => Mojo::IOLoop->singleton, app => app);
 
-# Header condition plugin
-plugin 'header_condition';
+# Missing plugin
+eval { plugin 'does_not_exist'; };
+is $@, "Plugin \"does_not_exist\" missing, maybe you need to install it?\n",
+  'right error';
 
 # Plugin with a template
 use FindBin;
@@ -58,6 +59,12 @@ is app->test_helper2, 'Mojolicious::Controller', 'right value';
 # Test renderer
 app->renderer->add_handler(dead => sub { die 'renderer works!' });
 
+# GET /☃
+get '/☃' => sub {
+  my $self = shift;
+  $self->render_text($self->url_for);
+};
+
 # GET /unicode/a%E4b
 get '/unicode/aäb' => sub {
   my $self = shift;
@@ -70,6 +77,16 @@ get '/unicode/:stuff' => sub {
   $self->render(text => $self->param('stuff') . $self->url_for);
 };
 
+# GET /conditional
+get '/conditional' => (
+  cb => sub {
+    my ($r, $c, $captures) = @_;
+    $captures->{condition} = $c->req->headers->header('X-Condition');
+    return unless $captures->{condition};
+    1;
+  }
+) => {inline => '<%= $condition %>'};
+
 # GET /
 get '/' => 'root';
 
@@ -253,7 +270,12 @@ get '/inline/ep/partial' => sub {
 };
 
 # GET /source
-get '/source' => sub { shift->render_static('../lite_app.t') };
+get '/source' => sub {
+  my $self = shift;
+  my $file = $self->param('fail') ? 'does_not_exist.txt' : '../lite_app.t';
+  $self->render_static($file)
+    or $self->render_text('does not exist!', status => 404);
+};
 
 # GET /foo_relaxed/*
 get '/foo_relaxed/(.test)' => sub {
@@ -599,7 +621,7 @@ under sub {
   return unless $self->req->headers->header('X-Bender');
   $self->res->headers->add('X-Under' => 23);
   $self->res->headers->add('X-Under' => 24);
-  return 1;
+  1;
 };
 
 # GET /with_under
@@ -623,7 +645,7 @@ under sub {
 
   # Not authenticated
   $self->render('param_auth_denied');
-  return;
+  undef;
 };
 
 # GET /param_auth
@@ -639,18 +661,32 @@ under sub {
   $self->cookie(foo => 'cookie', {expires => (time + 60)});
   $self->signed_cookie(bar => 'signed_cookie', {expires => (time + 120)});
   $self->cookie(bad => 'bad_cookie--12345678');
-  return 1;
+  1;
 };
 
 # GET /bridge2stash
 get '/bridge2stash' =>
   sub { shift->render(template => 'bridge2stash', handler => 'ep'); };
 
+# Make sure after_dispatch can make session changes
+hook after_dispatch => sub {
+  my $self = shift;
+  return unless $self->req->url->path =~ /^\/late\/session/;
+  $self->session(late => 'works!');
+};
+
+# GET /late/session
+get '/late/session' => sub {
+  my $self = shift;
+  my $late = $self->session('late') || 'not yet!';
+  $self->render_text($late);
+};
+
 # Counter
 my $under = 0;
 under sub {
   shift->res->headers->header('X-Under' => ++$under);
-  return 1;
+  1;
 };
 
 # GET /with_under_count
@@ -659,7 +695,7 @@ get '/with/under/count';
 # Everything gets past this
 under sub {
   shift->res->headers->header('X-Possible' => 1);
-  return 1;
+  1;
 };
 
 # GET /possible
@@ -668,7 +704,7 @@ get '/possible' => 'possible';
 # Nothing gets past this
 under sub {
   shift->res->headers->header('X-Impossible' => 1);
-  return 0;
+  0;
 };
 
 # GET /impossible
@@ -706,6 +742,9 @@ $tua->ioloop->timer(
   }
 );
 
+# GET /☃
+$t->get_ok('/☃')->status_is(200)->content_is('/%E2%98%83');
+
 # GET /unicode/a%E4b
 $t->get_ok('/unicode/a%E4b')->status_is(200)->content_is('/unicode/a%E4b');
 
@@ -719,6 +758,13 @@ $t->get_ok('/unicode/a b')->status_is(200)->content_is('a b/unicode/a%20b');
 # GET /unicode/a\b
 $t->get_ok('/unicode/a\\b')->status_is(200)->content_is('a\\b/unicode/a%5Cb');
 
+# GET /conditional
+$t->get_ok('/conditional' => {'X-Condition' => 'Conditions rock!'})
+  ->status_is(200)->content_is("Conditions rock!\n");
+
+# GET /conditional (missing header)
+$t->get_ok('/conditional')->status_is(404)->content_is("Oops!\n");
+
 # GET /
 $t->get_ok('/')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')
   ->header_is('X-Powered-By' => 'Mojolicious (Perl)')
@@ -972,9 +1018,9 @@ $t->get_ok('/.html')->status_is(200)
   "/root.html\n/root.html\n/root.html\n/root.html\n/root.html\n");
 
 # GET /0 ("X-Forwarded-For")
+my $source = $t->tx->local_address;
 $t->get_ok('/0', {'X-Forwarded-For' => '192.168.2.2, 192.168.2.1'})
-  ->status_is(200)
-  ->content_like(qr/http\:\/\/localhost\:\d+\/0\-127\.0\.0\.1\-0/);
+  ->status_is(200)->content_like(qr/http\:\/\/localhost\:\d+\/0\-$source\-0/);
 
 # GET /0 (reverse proxy with "X-Forwarded-For")
 my $backup2 = $ENV{MOJO_REVERSE_PROXY};
@@ -986,27 +1032,26 @@ $ENV{MOJO_REVERSE_PROXY} = $backup2;
 
 # GET /0 ("X-Forwarded-Host")
 $t->get_ok('/0', {'X-Forwarded-Host' => 'mojolicio.us:8080'})->status_is(200)
-  ->content_like(qr/http\:\/\/localhost\:\d+\/0\-127\.0\.0\.1\-0/);
+  ->content_like(qr/http\:\/\/localhost\:\d+\/0\-$source\-0/);
 
 # GET /0 (reverse proxy with "X-Forwarded-Host")
 $backup2 = $ENV{MOJO_REVERSE_PROXY};
 $ENV{MOJO_REVERSE_PROXY} = 1;
 $t->get_ok('/0', {'X-Forwarded-Host' => 'mojolicio.us:8080'})->status_is(200)
-  ->content_is('http://mojolicio.us:8080/0-127.0.0.1-0');
+  ->content_is("http://mojolicio.us:8080/0-$source-0");
 $ENV{MOJO_REVERSE_PROXY} = $backup2;
 
 # GET /0 ("X-Forwarded-HTTPS" and "X-Forwarded-Host")
 $t->get_ok('/0',
   {'X-Forwarded-HTTPS' => 1, 'X-Forwarded-Host' => 'mojolicio.us'})
-  ->status_is(200)
-  ->content_like(qr/http\:\/\/localhost\:\d+\/0\-127\.0\.0\.1\-0/);
+  ->status_is(200)->content_like(qr/http\:\/\/localhost\:\d+\/0\-$source\-0/);
 
 # GET /0 (reverse proxy with "X-Forwarded-HTTPS" and "X-Forwarded-Host")
 $backup2 = $ENV{MOJO_REVERSE_PROXY};
 $ENV{MOJO_REVERSE_PROXY} = 1;
 $t->get_ok('/0',
   {'X-Forwarded-HTTPS' => 1, 'X-Forwarded-Host' => 'mojolicio.us'})
-  ->status_is(200)->content_is('https://mojolicio.us/0-127.0.0.1-0');
+  ->status_is(200)->content_is("https://mojolicio.us/0-$source-0");
 $ENV{MOJO_REVERSE_PROXY} = $backup2;
 
 # DELETE /inline/epl
@@ -1025,6 +1070,9 @@ $t->get_ok('/inline/ep/partial')->status_is(200)
 # GET /source
 $t->get_ok('/source')->status_is(200)->content_like(qr/get_ok\('\/source/);
 
+# GET /source (file does not exist)
+$t->get_ok('/source?fail=1')->status_is(404)->content_is('does not exist!');
+
 # GET / (with body and max message size)
 $backup2 = $ENV{MOJO_MAX_MESSAGE_SIZE} || '';
 $ENV{MOJO_MAX_MESSAGE_SIZE} = 1024;
@@ -1551,13 +1599,31 @@ $t->get_ok('/redirect/condition/1' => {'X-Condition-Test' => 1})
 $t->get_ok('/bridge2stash' => {'X-Flash' => 1})->status_is(200)
   ->content_is("stash too!!!!!!!!\n");
 
+# GET /bridge2stash (with cookies, session and flash)
+$t->get_ok('/bridge2stash')->status_is(200)
+  ->content_is(
+  "stash too!cookie!signed_cookie!!bad_cookie--12345678!session!flash!/!\n");
+
+# GET /bridge2stash (broken session cookie)
+$t->reset_session;
+my $session = b("☃☃☃☃☃")->b64_encode('');
+my $hmac    = $session->clone->hmac_md5_sum($t->ua->app->secret);
+my $broken  = "\$Version=1; mojolicious=$session--$hmac; \$Path=/";
+$t->get_ok('/bridge2stash' => {Cookie => $broken})->status_is(200)
+  ->content_is("stash too!!!!!!!/!\n");
+
+# GET /bridge2stash (fresh start)
+$t->reset_session;
+$t->get_ok('/bridge2stash' => {'X-Flash' => 1})->status_is(200)
+  ->content_is("stash too!!!!!!!!\n");
+
 # GET /favicon.ico (random static requests)
 $t->get_ok('/favicon.ico')->status_is(200);
 $t->get_ok('/mojolicious-white.png')->status_is(200);
 $t->get_ok('/mojolicious-black.png')->status_is(200);
 $t->get_ok('/favicon.ico')->status_is(200);
 
-# GET /bridge2stash (with cookies, session and flash)
+# GET /bridge2stash (with cookies, session and flash again)
 $t->get_ok('/bridge2stash')->status_is(200)
   ->content_is(
   "stash too!cookie!signed_cookie!!bad_cookie--12345678!session!flash!/!\n");
@@ -1571,6 +1637,15 @@ $t->get_ok('/bridge2stash' => {'X-Flash2' => 1})->status_is(200)
 $t->get_ok('/bridge2stash')->status_is(200)
   ->content_is("stash too!cookie!signed_cookie!!bad_cookie--12345678!!!!\n");
 
+# GET /late/session (late session does not affect rendering)
+$t->get_ok('/late/session')->status_is(200)->content_is('not yet!');
+
+# GET /late/session (previous late session does affect rendering)
+$t->get_ok('/late/session')->status_is(200)->content_is('works!');
+
+# GET /late/session (previous late session does affect rendering again)
+$t->get_ok('/late/session')->status_is(200)->content_is('works!');
+
 # GET /with/under/count
 $t->get_ok('/with/under/count', {'X-Bender' => 'Rodriguez'})->status_is(200)
   ->header_is(Server         => 'Mojolicious (Perl)')
@@ -1650,8 +1725,6 @@ is $timer,
   "/root.html\n/root.html\n/root.html\n/root.html\n/root.html\nworks!",
   'right content';
 
-$ENV{MOJO_MODE} = $backup;
-
 __DATA__
 @@ with-format.html.ep
 <%= url_for 'without-format' %>
@@ -6,11 +6,10 @@ use warnings;
 use utf8;
 
 # Disable IPv6, epoll and kqueue
-BEGIN { $ENV{MOJO_NO_IPV6} = $ENV{MOJO_POLL} = 1 }
-
-# Development
-my $backup;
-BEGIN { $backup = $ENV{MOJO_MODE} || ''; $ENV{MOJO_MODE} = 'development' }
+BEGIN {
+  $ENV{MOJO_NO_IPV6} = $ENV{MOJO_POLL} = 1;
+  $ENV{MOJO_MODE} = 'development';
+}
 
 use Test::More tests => 9;
 
@@ -4,7 +4,10 @@ use strict;
 use warnings;
 
 # Disable IPv6, epoll and kqueue
-BEGIN { $ENV{MOJO_NO_IPV6} = $ENV{MOJO_POLL} = 1 }
+BEGIN {
+  $ENV{MOJO_NO_IPV6} = $ENV{MOJO_POLL} = 1;
+  $ENV{MOJO_MODE} = 'production';
+}
 
 use Test::More tests => 51;
 
@@ -18,9 +21,6 @@ use_ok 'MojoliciousTest';
 
 my $t = Test::Mojo->new(app => 'MojoliciousTest');
 
-my $backup = $ENV{MOJO_MODE} || '';
-$ENV{MOJO_MODE} = 'production';
-
 # SyntaxError::foo in production mode (syntax error in controller)
 $t->get_ok('/syntax_error/foo')->status_is(500)
   ->header_is(Server         => 'Mojolicious (Perl)')
@@ -81,5 +81,3 @@ $t->get_ok('/../../mojolicious/secret.txt')->status_is(404)
   ->header_is(Server         => 'Mojolicious (Perl)')
   ->header_is('X-Powered-By' => 'Mojolicious (Perl)')
   ->content_like(qr/Not Found/);
-
-$ENV{MOJO_MODE} = $backup;
@@ -6,7 +6,7 @@ use warnings;
 # Disable IPv6, epoll and kqueue
 BEGIN { $ENV{MOJO_NO_IPV6} = $ENV{MOJO_POLL} = 1 }
 
-use Test::More tests => 30;
+use Test::More tests => 45;
 
 # "Hey! Bite my glorious golden ass!"
 use Mojolicious::Lite;
@@ -27,6 +27,9 @@ get 'style';
 # GET /basicform
 get '/basicform';
 
+# GET /multibox
+get '/multibox';
+
 # GET /form
 get 'form/:test' => 'form';
 
@@ -92,8 +95,53 @@ $t->get_ok('/basicform')->status_is(200)->content_is(<<EOF);
 </form>
 EOF
 
+# GET /multibox
+$t->get_ok('/multibox')->status_is(200)->content_is(<<EOF);
+<form action="/multibox">
+  <input name="foo" type="checkbox" value="one" />
+  <input name="foo" type="checkbox" value="two" />
+  <input type="submit" value="Ok" />
+</form>
+EOF
+
+# GET /multibox (with one value)
+$t->get_ok('/multibox?foo=two')->status_is(200)->content_is(<<EOF);
+<form action="/multibox">
+  <input name="foo" type="checkbox" value="one" />
+  <input checked="checked" name="foo" type="checkbox" value="two" />
+  <input type="submit" value="Ok" />
+</form>
+EOF
+
+# GET /multibox (with one right and one wrong value)
+$t->get_ok('/multibox?foo=one&foo=three')->status_is(200)->content_is(<<EOF);
+<form action="/multibox">
+  <input checked="checked" name="foo" type="checkbox" value="one" />
+  <input name="foo" type="checkbox" value="two" />
+  <input type="submit" value="Ok" />
+</form>
+EOF
+
+# GET /multibox (with wrong value)
+$t->get_ok('/multibox?foo=bar')->status_is(200)->content_is(<<EOF);
+<form action="/multibox">
+  <input name="foo" type="checkbox" value="one" />
+  <input name="foo" type="checkbox" value="two" />
+  <input type="submit" value="Ok" />
+</form>
+EOF
+
+# GET /multibox (with two values)
+$t->get_ok('/multibox?foo=two&foo=one')->status_is(200)->content_is(<<EOF);
+<form action="/multibox">
+  <input checked="checked" name="foo" type="checkbox" value="one" />
+  <input checked="checked" name="foo" type="checkbox" value="two" />
+  <input type="submit" value="Ok" />
+</form>
+EOF
+
 # GET /form
-$t->get_ok('/form/lala?a=b&b=0&c=2&d=3&escaped=1%22+%222')->status_is(200)
+$t->get_ok('/form/lala?a=2&b=0&c=2&d=3&escaped=1%22+%222')->status_is(200)
   ->content_is(<<EOF);
 <form action="/links" method="post">
   <input name="foo" />
@@ -119,8 +167,8 @@ $t->get_ok('/form/lala?a=b&b=0&c=2&d=3&escaped=1%22+%222')->status_is(200)
   <input name="foo" />
 </form>
 <input name="escaped" value="1&quot; &quot;2" />
-<input name="a" value="b" />
-<input name="a" value="b" />
+<input name="a" value="2" />
+<input name="a" value="2" />
 EOF
 
 # GET /form (alternative)
@@ -263,6 +311,13 @@ __DATA__
   %= submit_button
 %= end
 
+@@ multibox.html.ep
+%= form_for multibox => begin
+  %= check_box foo => 'one'
+  %= check_box foo => 'two'
+  %= submit_button
+%= end
+
 @@ form.html.ep
 <%= form_for 'links', method => 'post' => begin %>
   <%= input_tag 'foo' %>
@@ -4,7 +4,10 @@ use strict;
 use warnings;
 
 # Disable IPv6, epoll and kqueue
-BEGIN { $ENV{MOJO_NO_IPV6} = $ENV{MOJO_POLL} = 1 }
+BEGIN {
+  $ENV{MOJO_NO_IPV6} = $ENV{MOJO_POLL} = 1;
+  $ENV{MOJO_MODE} = 'testing';
+}
 
 use Test::More tests => 26;
 
@@ -18,9 +21,6 @@ use_ok 'MojoliciousTest';
 
 my $t = Test::Mojo->new(app => 'MojoliciousTest');
 
-my $backup = $ENV{MOJO_MODE} || '';
-$ENV{MOJO_MODE} = 'testing';
-
 # SyntaxError::foo in testing mode (syntax error in controller)
 $t->get_ok('/syntax_error/foo')->status_is(500)
   ->header_is(Server         => 'Mojolicious (Perl)')
@@ -51,5 +51,3 @@ $t->get_ok('/../../mojolicious/secret.txt')->status_is(404)
   ->header_is(Server         => 'Mojolicious (Perl)')
   ->header_is('X-Powered-By' => 'Mojolicious (Perl)')
   ->content_like(qr/Testing not found/);
-
-$ENV{MOJO_MODE} = $backup;